<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>src\cmpage\model\page.js</title>
  
    <link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
    <link rel="stylesheet" href="../assets/css/main.css" id="site_styles">
    <link rel="stylesheet" href="../assets/vendor/bootstrap/css/bootstrap.min.css">
    <link rel="shortcut icon" type="image/png" href="../assets/favicon.png">
</head>
<body class="yui3-smart">
 <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
        <div class="container-fluid">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
               <a class="navbar-brand mainlogo" href="/static/doc/index.html">
             
            <img alt="" src="../assets/css/logo.png" title="">
            
                
          </a>
            </div>
            <div id="navbar" class="navbar-collapse collapse">
                 <ul class="nav navbar-nav">
                    
                    <li><a href="/home/index/index">首页</a>
                    </li>
                    
                    <li><a href="/static/doc/index.html">文档</a>
                    </li>
                    
                    <li><a href="/admin/index/index">演示</a>
                    </li>
                    
                    <li><a href="/home/index/log">日志</a>
                    </li>
                    
                </ul>
               <div class="navbar-form navbar-right filterAPi" autocomplete="off">
                <input type="text" id='txtSearchAPI' class="form-control search-query" placeholder="Search for API" />
                 <ul id="filterList" class="filterItems dropdown-menu" role="menu"></ul>
                </div>
            </div>
        </div>
    </nav>
    <div id="sidebar">
    <h3>Modules/Classes</h3>
        <div id="api-tabview-filter">
            <input id='txtSearch' type="search" class="form-control" placeholder="Type to filter Modules/Classes">
        </div>
        <dl id="sidebar_list">
             
                <dt>
                    <span class="glyphicon glyphicon-minus"></span>
                    <a href="../modules/admin.controller.html">admin.controller</a>
                </dt>
                <dd>
                    <ul>
                   
                       <li>
                            
                           <a href="../classes/admin.controller.base.html">admin.controller.base</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/admin.controller.code.html">admin.controller.code</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/admin.controller.index.html">admin.controller.index</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/admin.controller.mob.html">admin.controller.mob</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                    </ul>
                </dd>
             
                <dt>
                    <span class="glyphicon glyphicon-minus"></span>
                    <a href="../modules/admin.model.html">admin.model</a>
                </dt>
                <dd>
                    <ul>
                   
                       <li>
                            
                           <a href="../classes/admin.model.code.html">admin.model.code</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/admin.model.code_list.html">admin.model.code_list</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/admin.model.code_lookup.html">admin.model.code_lookup</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/admin.model.groupuser.html">admin.model.groupuser</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/admin.model.groupuser_add.html">admin.model.groupuser_add</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/admin.model.log.html">admin.model.log</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/admin.model.login.html">admin.model.login</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/admin.model.privilege.html">admin.model.privilege</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/admin.model.teamuser.html">admin.model.teamuser</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/admin.model.teamuser_add.html">admin.model.teamuser_add</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/admin.model.user.html">admin.model.user</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                    </ul>
                </dd>
             
                <dt>
                    <span class="glyphicon glyphicon-minus"></span>
                    <a href="../modules/cmpage.controller.html">cmpage.controller</a>
                </dt>
                <dd>
                    <ul>
                   
                       <li>
                            
                           <a href="../classes/cmpage.controller.base.html">cmpage.controller.base</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/cmpage.controller.mob.html">cmpage.controller.mob</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/cmpage.controller.module.html">cmpage.controller.module</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/cmpage.controller.page.html">cmpage.controller.page</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/cmpage.controller.utils.html">cmpage.controller.utils</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                    </ul>
                </dd>
             
                <dt>
                    <span class="glyphicon glyphicon-minus"></span>
                    <a href="../modules/cmpage.logic.html">cmpage.logic</a>
                </dt>
                <dd>
                    <ul>
                   
                       <li>
                            
                           <a href="../classes/cmpage.logic.page.html">cmpage.logic.page</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                    </ul>
                </dd>
             
                <dt>
                    <span class="glyphicon glyphicon-minus"></span>
                    <a href="../modules/cmpage.model.html">cmpage.model</a>
                </dt>
                <dd>
                    <ul>
                   
                       <li>
                            
                           <a href="../classes/cmpage.model.area.html">cmpage.model.area</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/cmpage.model.base.html">cmpage.model.base</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/cmpage.model.file_list.html">cmpage.model.file_list</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/cmpage.model.page.html">cmpage.model.page</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/cmpage.model.page_excel.html">cmpage.model.page_excel</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/cmpage.model.page_lookup.html">cmpage.model.page_lookup</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/cmpage.model.page_mob.html">cmpage.model.page_mob</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/cmpage.model.utils.html">cmpage.model.utils</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/cmpage.cmpage_global.html">cmpage.cmpage_global</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/cmpage.cmpage_global_flow.html">cmpage.cmpage_global_flow</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                    </ul>
                </dd>
             
                <dt>
                    <span class="glyphicon glyphicon-minus"></span>
                    <a href="../modules/demo.model.html">demo.model</a>
                </dt>
                <dd>
                    <ul>
                   
                       <li>
                            
                           <a href="../classes/flow.model.proc_assign.html">flow.model.proc_assign</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/cmpage.model.appr.html">cmpage.model.appr</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/flow.model.proc.html">flow.model.proc</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/flow.model.task.html">flow.model.task</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/flow.model.task_act.html">flow.model.task_act</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/flow.model.task_act_appr.html">flow.model.task_act_appr</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                    </ul>
                </dd>
             
                <dt>
                    <span class="glyphicon glyphicon-minus"></span>
                    <a href="../modules/flow.controller.html">flow.controller</a>
                </dt>
                <dd>
                    <ul>
                   
                       <li>
                            
                           <a href="../classes/flow.controller.act.html">flow.controller.act</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/flow.controller.base.html">flow.controller.base</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/flow.controller.proc.html">flow.controller.proc</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/flow.controller.task.html">flow.controller.task</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/flow.controller.task_act.html">flow.controller.task_act</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                    </ul>
                </dd>
             
                <dt>
                    <span class="glyphicon glyphicon-minus"></span>
                    <a href="../modules/flow.model.html">flow.model</a>
                </dt>
                <dd>
                    <ul>
                   
                       <li>
                            
                           <a href="../classes/flow.model.act.html">flow.model.act</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                       <li>
                            
                           <a href="../classes/flow.model.act_path.html">flow.model.act_path</a>
                           <ul>
                                
                           </ul>
                       </li>
                    
                    </ul>
                </dd>
             
        </dl>
</div>
   
    <div class="stdoc-content">
        <!--     <form id="options-form" class="form-inline pull-right">
        Show:
        <label for="api-show-inherited" class="checkbox">
            <input type="checkbox" id="api-show-inherited" checked>
            Inherited
        </label>

        <label for="api-show-protected" class="checkbox">
            <input type="checkbox" id="api-show-protected">
            Protected
        </label>

        <label for="api-show-private" class="checkbox">
            <input type="checkbox" id="api-show-private">
            Private
        </label>
        <label for="api-show-deprecated" class="checkbox">
            <input type="checkbox" id="api-show-deprecated">
            Deprecated
        </label>

    </form>

 -->
        <div class="apidocs">
            <div id="docs-main">
                <div class="content">
                    <div class="page-header">
    <h1>src\cmpage\model\page.js <small>File</small></h1>
</div>

<div class="file">
    <pre class="prettyprint linenums" id='src_code'>
&#x27;use strict&#x27;;
// +----------------------------------------------------------------------
// | CmPage [ 通用页面框架 ]
// +----------------------------------------------------------------------
// | Licensed under the Apache License, Version 2.0
// +----------------------------------------------------------------------
// | Author: defans &lt;defans@sina.cn&gt;
// +----------------------------------------------------------------------

/**

 @module cmpage.model
 */

/**
 * 普通页面的数据处理类，实现了具体的操作方法
 * @class cmpage.model.page
 */
 import Base from &#x27;./base.js&#x27;;

export default class extends Base {

        mod = {};   //模块主设置信息，及传入的参数等
        modQuerys = {}; //模块查询列设置信息
        modCols = {};    //模块显示列设置信息
        modEdits = {};   //模块编辑列设置信息
        modBtns = {};    //模块按钮设置信息
        list = {};     //结果列表集
        rec = {};      //当前记录
        proc = {};      //相关工作流模板对象

    /**
     * 初始化设置页面参数
     * @method  initPage
     */
    async initPage(){
        if(this.mod.c_proc &gt;0){     //流程模板的主业务类
            this.proc = await cmpage.model(&#x27;flow/proc&#x27;).getProcById(this.mod.c_proc);
            this.proc.c_link_model = this.mod.c_path;   //设置流程模板的关联类和表
            this.proc.c_link_type = this.mod.c_table;
            this.proc.linkModulename = this.mod.c_modulename;
        }
        this.mod.c_other = think.isEmpty(this.mod.c_other) ? {}:cmpage.objFromString(this.mod.c_other) ;
        this.mod.c_module_slave = think.isEmpty(this.mod.c_module_slave) ? {}:cmpage.objFromString(this.mod.c_module_slave) ;

    }

    /**
     * 取查询项的设置，组合成HTML输出
     * @method  htmlGetQuery
     * @return {Array}  查询的HTML片段，包括 bjui-moreSearch 部分
     */
    async htmlGetQuery(){
        let html =[];
        let html0 = [];
        let provinceValue =&#x27;&#x27;;
        let cityValue=&#x27;&#x27;;
        let k =0;
        for(let col of this.modQuerys){
            if (col.c_isshow) {
                if(k &gt;=this.mod.user.queryColumns &amp;&amp; k !== -1){
                    for(let h of html){    html0.push(h);       }
                    html0.push(&#x27;&lt;button type=&quot;button&quot; class=&quot;showMoreSearch&quot; data-toggle=&quot;moresearch&quot; data-name=&quot;custom&quot;&gt;&lt;i class=&quot;fa fa-angle-double-down&quot;&gt;&lt;/i&gt;&lt;/button&gt;&#x27;);
                    html =[];
                    k = -1;
                }
                if(!think.isEmpty(this.mod.query[col.c_column])){
                    col.c_default = this.mod.query[col.c_column];
                }
                if(col.c_type !== &quot;hidden&quot; &amp;&amp; col.c_type !== &quot;provinceSelect&quot; &amp;&amp; col.c_type !== &quot;citySelect&quot; &amp;&amp; col.c_type !== &quot;countrySelect&quot; &amp;&amp; col.c_type !== &quot;fixed&quot;)                {
                    html.push(&#x60;&lt;label  &gt;${col.c_name}&lt;/label&gt;&#x60;);
                    if(k !== -1){ k += 1; }
                }
                if (col.c_type === &quot;hidden&quot;){
                    html.push(&#x60;&lt;input id=&quot;query${this.mod.c_modulename}_${col.c_column}&quot; name=&quot;${col.c_column}&quot; type=&quot;hidden&quot; value=&quot;${col.c_default}&quot;   /&gt;&#x60;);
                }else  if (col.c_coltype === &quot;datetime&quot; || col.c_coltype === &quot;date&quot; || col.c_coltype === &quot;timestamp&quot;){
                    html.push(&#x60;&lt;input type=&quot;text&quot; id=&quot;query${this.mod.c_modulename}_${col.c_column}&quot; name=&quot;${col.c_column}&quot; value=&quot;${col.c_default}&quot; data-toggle=&quot;datepicker&quot; data-rule=&quot;date&quot; size=&quot;12&quot; class=&quot;form-control&quot; /&gt;&#x60;);
                }else if (col.c_coltype === &quot;bool&quot;){
                    html.push(&#x60;&lt;input type=&quot;checkbox&quot; id=&quot;query${this.mod.c_modulename}_${col.c_column}&quot; name=&quot;${col.c_column}&quot; data-toggle=&quot;icheck&quot; value=&quot;true&quot; data-label=&quot;是&quot;
                        ${col.c_default ? &quot;checked=checked&quot; : &quot;&quot;} class=&quot;form-control&quot; /&gt;&#x60;);
                }else if (col.c_type === &quot;select&quot;){
                    let options = await this.getOptions(col,true);
                    html.push(&#x60;&lt;select id=&quot;query${this.mod.c_modulename}_${col.c_column}&quot; name=&quot;${col.c_column}&quot; data-toggle=&quot;selectpicker&quot; &gt; ${options} &lt;/select&gt;&#x60;);
                } else if (col.c_type === &quot;selectTree&quot; || col.c_type === &quot;selectTreeMultiple&quot;) {
                    let treeOptions = await this.getOptionsTree(col,true);
                    html.push(&#x60;&lt;input id=&quot;query${this.mod.c_modulename + col.c_column}&quot; name=&quot;${col.c_column}&quot;  type=&quot;hidden&quot; value=&quot;${col.c_default}&quot; /&gt;
                        &lt;input name=&quot;${col.c_column}Show&quot; type=&quot;text&quot; size=&quot;25&quot; value=&quot;${treeOptions.selectName}&quot; data-toggle=&quot;selectztree&quot; data-tree=&quot;#selectTreeQuery${this.mod.c_modulename + col.c_column}&quot;   readonly /&gt;
                        &lt;ul id=&quot;selectTreeQuery${this.mod.c_modulename + col.c_column}&quot; class=&quot;ztree hide&quot; data-toggle=&quot;ztree&quot; data-expand-all=&quot;false&quot; data-check-enable=&quot;true&quot;
                        data-value-input=&quot;query${this.mod.c_modulename + col.c_column}&quot; ${(col.c_type === &quot;selectTree&quot; ? &#x27; data-chk-style=&quot;radio&quot; data-radio-type=&quot;all&quot; &#x27;:&#x27; &#x27;)}
                        data-on-check=&quot;selectNodeCheck&quot; data-on-click=&quot;selectNodeClick&quot; &gt; ${treeOptions.options} &lt;/ul&gt;&#x60;);
                }else if (col.c_type === &quot;lookup&quot;){
                    html.push(&#x60;&lt;input id=&quot;query${this.mod.c_modulename}_${col.c_column}&quot; name=&quot;${col.c_column}&quot; type=&quot;lookup&quot; size=&quot;10&quot; value=&quot;${col.c_default}&quot;  data-width=&quot;800&quot; data-height=&quot;600&quot;
                        data-toggle=&quot;lookup&quot; data-title=&quot;${col.c_name} 选择&quot; data-url=&quot;${this.getReplaceToSpecialChar(col.c_memo)}&quot; readonly=&quot;readonly&quot; /&gt;&#x60;);
                }else if (col.c_type === &quot;provinceSelect&quot;){
                    html.push(&#x60;&lt;select name=&quot;c_province&quot; data-toggle=&quot;selectpicker&quot;  data-nextselect=&quot;#city${this.mod.c_modulename}Query&quot;
                        data-refurl=&quot;/cmpage/utils/get_citys?province={value}&quot;&gt;  ${await cmpage.model(&#x27;cmpage/area&#x27;).getProvinceItems(col.c_default,true)} &lt;/select&gt;&#x60;);
                    provinceValue = col.c_default;
                }else if (col.c_type === &quot;citySelect&quot;){
                    html.push(&#x60;&lt;select name=&quot;c_city&quot; id=&quot;city${this.mod.c_modulename}Query&quot; data-toggle=&quot;selectpicker&quot; data-nextselect=&quot;#country${this.mod.c_modulename}Query&quot;
                        data-refurl=&quot;/cmpage/utils/get_countrys?city={value}&quot;&gt;${await cmpage.model(&#x27;cmpage/area&#x27;).getCityItems(col.c_default,true,provinceValue )} &lt;/select&gt;&#x60;);
                    cityValue = col.c_default;
                }else if (col.c_type === &quot;countrySelect&quot;){
                    html.push(&#x60;&lt;select name=&quot;c_country&quot; id=&quot;country${this.mod.c_modulename}Query&quot; data-toggle=&quot;selectpicker&quot; &gt;${await cmpage.model(&#x27;cmpage/area&#x27;).getCountryItems(col.c_default,true,cityValue)} &lt;/select&gt;&#x60;);
                }else if( col.c_type !== &quot;fixed&quot;){
                    html.push(&#x60;&lt;input id=&quot;query${this.mod.c_modulename}_${col.c_column}&quot; name=&quot;${col.c_column}&quot; type=&quot;${col.c_type}&quot; size=&quot;${col.c_width}&quot; value=&quot;${col.c_default}&quot; data-rule=&quot;${col.c_memo}&quot; class=&quot;form-control&quot;  /&gt;&#x60;);
                }
            }
        }

        if(html0.length === 0){     //如果不超过 3 项查询的时候
            html0 = html;
            html = [];
        }
        return [html0.join(&#x27; &#x27;), html.join(&#x27; &#x27;)];
    }

    /**
     * 输出额外的按钮和js函数和HTML片段，区别于 getPageOther
     * @method  htmlGetOther
     * @return {string}  html片段
     */
    async htmlGetOther(){
        return &#x60;&#x60;;
    }

    /**
     * 取下拉框的选项集
     * @method  getOptions
     * @return {string}  下拉框选项的HTML片段
     * @param   {object} md 下拉项的设置，其中md.c_default为默认值，可以在调用本方法前修改
     * @param   {bool} [isBlank=false]   下拉项中是否增加空项，一般查询项是需要的
     */
    async getOptions(md, isBlank){
        let items = [];
        if (md.c_type == &quot;select&quot;) {          //下拉框设置
            //cmpage.debug(md.c_memo);
            if(isBlank){
                items.push(&#x27;&lt;option value=&quot;0&quot;&gt; &lt;/option&gt;&#x27;);
            }
            if (/^select*/.test(md.c_memo)) {    //以select开头
                //let sql = md.c_memo.replace(/#group#/,think.session(&#x27;groupID&#x27;)).replace(/##/,&quot;&#x27;&quot;);
                let sql = md.c_memo;
                let list = await this.query(sql);
                for(let rec of list) {
                    items.push( &#x60;&lt;option value=&#x27;${rec.id}&#x27; ${rec.id === md.c_default ? &quot;selected&quot; : &quot;&quot;} &gt;${rec.c_name} &lt;/option&gt;&#x60;);
                }
            }else {
                if (/^\[{\w+/.test(md.c_memo)) {    //以 [ 开头       //设置如：[{##value##:true,##text##:##男##},{##value##:false,##text##:##女##}]
                    let its = (think.isString(md.c_memo) ? JSON.parse(md.c_memo.replace(/##/ig,&#x27;\&quot;&#x27;)) : []);
                    for (let it of its) {
                        items.push(&#x60;&lt;option value=&#x27;${it.value}&#x27; ${it.value === md.c_default ? &quot;selected&quot; : &quot;&quot;} &gt;${it.text} &lt;/option&gt;&#x60;);
                    }
                }else{
                    let its = md.c_memo.trim().split(&#x27;:&#x27;);        //设置如： admin/code:getParmsByPid:3
                    let parms = [];
                    let fnModel = cmpage.model(its[0]);     //通过某个模块的某个方法取下拉设置
                    if(think.isFunction(fnModel[its[1]])){
                        if(its.length &gt; 2){
                            parms = await fnModel[ its[1] ](its[2]);
                        }else{
                            parms = await fnModel[ its[1] ]();
                        }
                    }
                    //cmpage.debug(parms);
                    //如果设置有字段和连接字符的参数，形如： admin/code:getParmsByPid:3:c_ucode,c_name:-
                    let fieldNames = its.length &gt;3 ? its[3] : &#x27;&#x27;;
                    let joinStr =  its.length &gt;4 ? its[4] : &#x27;,&#x27;;
                    for (let parm of parms) {
                        let text = its.length &gt;3 ? cmpage.strGetValuesByPropertyName(parm, fieldNames, joinStr) : parm.c_name;
                        items.push(&#x60;&lt;option value=&#x27;${parm.id}&#x27; &quot;  ${parm.id == md.c_default ? &quot;selected&quot; : &quot;&quot;} &gt;${text}&lt;/option&gt;&#x60;);
                    }
                }
            }
        }
//        cmpage.debug(items.join(&#x27; &#x27;));
        return items.join(&#x27; &#x27;);
    }

    /**
     * 取树状下拉框的选项集
     * @method  getOptionsTree
     * @return {Array}  查询的HTML片段，包括 bjui-moreSearch 部分
     * @param   {object} md 下拉项的设置，其中md.c_default为默认值，可以在调用本方法前修改
     * @param   {bool} [isBlank=false]   下拉项中是否增加空项，一般查询项是需要的
     */
    async getOptionsTree(md, isBlank){
        let selectName = &#x27;&#x27;;
        let items = [];
        if (md.c_type.indexOf(&quot;select&quot;) ===0) {          //下拉框设置
            //cmpage.debug(md.c_memo);
            if(isBlank){
                items.push(&#x60;&lt;li data-id=&#x27;0&#x27; data-pid=&#x27;0&#x27; data-checked=true &gt; (不选择) &lt;/li&gt;&#x60;);
            }
            if (md.c_memo.indexOf(&#x27;select&#x27;) ===0) {    //以select开头
                //let sql = md.c_memo.replace(/#group#/,think.session(&#x27;groupID&#x27;)).replace(/##/,&quot;&#x27;&quot;);
                let sql = md.c_memo;
                let list = await this.query(sql);
                for(let rec of list) {
                    if(rec.id == md.c_default)  selectName += (think.isEmpty(selectName) ? &#x27;&#x27;:&#x27;,&#x27;) +think.isEmpty(rec.name) ? rec.c_name : rec.name;
                    items.push( &#x60;&lt;li data-id=&#x27;${rec.id}&#x27; data-pid=&#x27;${think.isEmpty(rec.pid) ? rec.c_pid : rec.pid}&#x27; + ${rec.id == md.c_default} ? &quot;data-checked=true&quot; : &quot;&quot;}
                            ${rec.checkDisalbed ? &quot;data-chk-disabled=true  &quot; : &quot; &quot;} ${list.indexOf(rec) == 0 ? &quot;data-open=true &quot; : &quot; &quot;} &gt;${think.isEmpty(rec.name) ? rec.c_name : rec.name}&lt;/li&gt;&#x60;);
                }
            }else {
                let its = md.c_memo.trim().split(&#x27;:&#x27;);        //设置如： admin/code:getTreeList:3
                let list = [];
                let fnModel = cmpage.model(its[0]);     //通过某个模块的某个方法取下拉设置
                if(think.isFunction(fnModel[its[1]])){
                    if(its.length === 3){
                        let parms = its[2].split(&#x27;,&#x27;);
                        list = await fnModel[ its[1] ](...parms);
                    }else{
                        list = await fnModel[ its[1] ]();
                    }
                }
                //cmpage.debug(parms);
                for (let rec of list) {
                    if(rec.id == md.c_default)  selectName += (think.isEmpty(selectName) ? &#x27;&#x27;:&#x27;,&#x27;) +think.isEmpty(rec.name) ? rec.c_name : rec.name;
                    items.push( &#x60;&lt;li data-id=&#x27;${rec.id}&#x27; data-pid=&#x27;${think.isEmpty(rec.pid) ? rec.c_pid : rec.pid}&#x27; + ${rec.id == md.c_default} ? &quot;data-checked=true&quot; : &quot;&quot;}
                            ${rec.checkDisalbed ? &quot;data-chk-disabled=true  &quot; : &quot; &quot;} ${list.indexOf(rec) == 0 ? &quot;data-open=true &quot; : &quot; &quot;} &gt;${think.isEmpty(rec.name) ? rec.c_name : rec.name}&lt;/li&gt;&#x60;);
                }
            }
        }
        //cmpage.debug(items.join(&#x27; &#x27;));
        debug(md,&#x27;page.getOptionsTree - md&#x27;);
        return {selectName:selectName, options:items.join(&#x27; &#x27;)};
    }

    /**
     * 根据设置取显示的替换值
     * @method  getReplaceText
     * @return {string}  替换的字符串
     * @param   {string} value 当前值
     * @param   {string} replaceItems  替换的设置值，支持两种方式
     *                      1. 函数如：admin/code:getXXXXXX
     *                      2. json如：[{value:true,text:&#x27;男&#x27;},{value:false,text:&#x27;女&#x27;}]
     */
    async getReplaceText(value,replaceItems){
        if (/^\[{\w+/.test(replaceItems)) {
            //let items = (think.isString(replaceItems) ? JSON.parse(replaceItems.replace(/##/ig,&#x27;\&quot;&#x27;)):replaceItems);
            let items = (think.isString(replaceItems) ? cmpage.arrFromString(replaceItems.replace(/##/ig,&#x27;\&#x27;&#x27;)):replaceItems);
            for(let item of items){
                if(item.value == value){
                    return item.text;
                }
            }
        }else
        {
            let its = replaceItems.split(&#x27;:&#x27;);        //设置如： admin/code:getNameById
            if(its.length &gt;1){
                let fnModel = cmpage.model(its[0]);     //通过某个模块的某个方法取下拉设置
                if(think.isFunction(fnModel[its[1]])){
                    let args =[];
                    args.push(value);
                    if(its.length &gt; 2){
                        for(let arg of its){
                            if(its.indexOf(arg) &gt;1)   args.push(arg);
                        }
                    }
                    return await fnModel[ its[1] ](...args);
                }
            }
        }

        return &quot;&quot;;
    }

    /**
     * 取顶部按钮的设置，分靠左和靠右两块，组合成HTML输出
     * @method  htmlGetBtnHeader
     * @return {string}  HTML片段
     */
    async htmlGetBtnHeader(){
      let html =[];
      let htmlRight =[];
      html.push(&#x60;&lt;button type=&quot;submit&quot; class=&quot;btn btn-default&quot; id=&quot;btnSearch${this.mod.c_modulename}&quot; data-icon=&quot;search&quot;&gt;
      ${this.mod.user.listColumns === cmpage.ui.enumListColumns.MOBILE ? &quot;&quot;:&quot;查询&quot;}&lt;/button&gt;&#x60;);
      if(!this.mod.parmsUrl.readonly){
          for(let btn of this.modBtns){
              btn.c_url = cmpage.objPropertysReplaceToStr(btn.c_url,this.mod.parmsUrl);
              if(btn.c_object.indexOf(&#x27;.Edit&#x27;) &gt;0 || btn.c_object.indexOf(&#x27;.Add&#x27;) &gt;0){
                  for(let p in this.mod.parmsUrl){
                      //自动添加列表模块的URL参数
                      if(![&quot;modulename&quot;,&quot;id&quot;,&quot;c_id&quot;,&quot;_&quot;].includes(p)){
                          btn.c_url += &#x60;&amp;${p}=${this.mod.parmsUrl[p]}&#x60;;
                      }
                  }
              }
              if(this.mod.user.listColumns === cmpage.ui.enumListColumns.MOBILE)    btn.c_label =&#x27;&#x27;;
                if(btn.c_isshow &amp;&amp; btn.c_location &lt;10 &amp;&amp; this.isShowBtn(null,btn)){
                    if(btn.c_location &lt;6){
                        html.push(&#x60;&lt;a class=&quot;${btn.c_class}&quot; data-toggle=&quot;${btn.c_opentype}&quot; data-options=&quot;${this.getReplaceToSpecialChar(btn.c_options)}&quot;  data-on-close=&quot;page${this.mod.c_modulename}Edit_onClose&quot;
                          data-icon=&quot;${btn.c_icon}&quot; href=&quot;${this.getReplaceToSpecialChar(btn.c_url)}&quot; data-title=&quot;${btn.c_title}&quot; data-on-load=&quot;pageRecList_load&quot;
                          onclick=&quot;${this.getReplaceToSpecialChar(btn.c_onclick)}&quot;&gt;${btn.c_label}&lt;/a&gt;&#x60;);
                    }else if(btn.c_location &gt;5 &amp;&amp; btn.c_location &lt;10){      //靠右放置
                        htmlRight.push(&#x60;&lt;a class=&quot;${btn.c_class}&quot; data-toggle=&quot;${btn.c_opentype}&quot; data-options=&quot;${this.getReplaceToSpecialChar(btn.c_options)}&quot;  data-on-close=&quot;page${this.mod.c_modulename}Edit_onClose&quot;
                          data-icon=&quot;${btn.c_icon}&quot; href=&quot;${this.getReplaceToSpecialChar(btn.c_url)}&quot; data-title=&quot;${btn.c_title}&quot; data-on-load=&quot;pageRecList_load&quot;
                          onclick=&quot;${this.getReplaceToSpecialChar(btn.c_onclick)}&quot;&gt;${btn.c_label}&lt;/a&gt;&#x60;);
                    }
                }
          }
      }
        //debug(this.mod.parmsUrl,&#x27;page.htmlGetBtnHeader - this.mod.parmsUrl&#x27;);
        if(this.mod.parmsUrl.moduleOpen !== &#x27;div&#x27;){
            htmlRight.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;btn btn-close &quot; data-icon=&quot;close&quot;&gt;${this.mod.user.listColumns === cmpage.ui.enumListColumns.MOBILE ? &quot;&quot;:&quot;关闭&quot;}&lt;/button&gt;&#x27;&#x60;);
        }
      return html.join(&#x27; &#x27;)+(htmlRight.length &gt;0 ? &#x27;&lt;div class=&quot;pull-right&quot;&gt;&#x27;+htmlRight.join(&#x27; &#x27;)+&#x27;&lt;/div&gt;&#x27;: &#x27;&#x27;);
    }

    /**
     * 取记录列表每一行的按钮设置，组合成HTML输出，子类中重写本方法可以定制每行按钮的输出效果
     * @method  htmlGetBtnList
     * @return {string}  HTML片段
     * @param   {object} rec 每行的记录对象
     */
    async htmlGetBtnList(rec){
        let html=[];
        let k=0;
        let btnMore = &#x27;&lt;div class=&quot;btn-group&quot;&gt; &lt;button type=&quot;button&quot; class=&quot;btn btn-default dropdown-toggle&quot; data-toggle=&quot;dropdown&quot;&gt;&#x27;
            +&#x27;更多&lt;span class=&quot;caret&quot;&gt;&lt;/span&gt; &lt;/button&gt; &lt;ul class=&quot;dropdown-menu&quot; role=&quot;menu&quot;&gt;&#x27;;
        for(let btn of this.modBtns){
            //if(btn.c_object == &#x27;OrderApplyList.ToOrder&#x27;) debug(btn,&#x27;page.htmlGetBtnList - btn&#x27;);
            if (btn.c_isshow &amp;&amp; btn.c_location &gt; 10 &amp;&amp; this.isShowBtn(rec,btn)) {
                k +=1;
                if(k === this.mod.user.listBtns +1)  html.push(btnMore);
                let btnUrl = this.getReplaceToSpecialChar(cmpage.objPropertysReplaceToStr(btn.c_url,rec));
                let btnClick = this.getReplaceToSpecialChar(cmpage.objPropertysReplaceToStr(btn.c_onclick,rec));
                let options = this.getReplaceToSpecialChar(btn.c_options);
                btn.c_label = k &gt;this.mod.user.listBtns ? (think.isEmpty(btn.c_label) ? btn.c_title : btn.c_label):btn.c_label;
                if(btn.c_object.indexOf(&#x27;.Edit&#x27;) &gt;0 || btn.c_object.indexOf(&#x27;.View&#x27;) &gt;0){
                    btnUrl += &#x60;&amp;listIds=${this.list.ids.join(&#x27;,&#x27;)}&#x60;;
                }
                html.push(&#x60; &lt;a type=&quot;button&quot; class=&quot;${btn.c_class}&quot; data-toggle=&quot;${btn.c_opentype}&quot; data-options=&quot;${options}&quot; title=&quot;${btn.c_title}&quot;
                             data-on-load=&quot;pageRecList_load&quot;  data-on-close=&quot;page${this.mod.c_modulename}Edit_onClose&quot; data-icon=&quot;${btn.c_icon}&quot; href=&quot;${btnUrl}&quot;
                            onclick=&quot;${btnClick}&quot; data-title=&quot;${btn.c_title}&quot;  style=&quot;${btn.c_style}&quot; &gt;${btn.c_label}&lt;/a&gt; &#x60;);
            }
        }
        //如果和流程相关，则显示流程节点的按钮
        if(!think.isEmpty(this.proc)){
            //debug(this.proc,&#x27;page.htmlGetBtnList - this.proc&#x27;);
            let actBtns = [];
            if(this.proc.c_type === cmpage.enumProcType.STATUSCHANGE){
                //直接取模板设置的按钮
                //debug(rec,&#x27;page.htmlGetBtnList - rec&#x27;);
                if(rec.c_act &gt; 0 ){
                    actBtns = await this.htmlGetActBtns(rec);
                }
            }else{
                //取当前任务节点的模板设置的按钮
                if(rec.c_task &gt; 0 ){
                    actBtns = await this.htmlGetTaskActBtns(rec);
                }
            }
            for(let btn of actBtns){
                k +=1;
                if(k === this.mod.user.listBtns +1)  html.push(btnMore);
                html.push(btn);
            }
        }
        if(k &gt;this.mod.user.listBtns){
            html.push(&#x27;&lt;/ul&gt;&lt;/div&gt;&#x27;);
        }
        return html.join(&#x27; &#x27;);
    }

    /**
     * 取分页列表的设置，结合结果数据集，组合成HTML输出，一般不需要重新本方法
     * @method  htmlGetList
     * @return {string}  HTML片段
     */
    async htmlGetList() {
        let html = [&#x27;&lt;thead&gt; &lt;tr &gt;&#x27;];
        let isShowBtns = this.mod.c_modulename.indexOf(&#x27;Lookup&#x27;) &gt;0;
        for (let btn of this.modBtns) {
            if (btn.c_location &gt; 9) {
                isShowBtns = true;
                break;
            }
        }
        //debug(this.mod.user, &#x27;page.htmlGetList - this.mod.user&#x27;);
        if(think.isEmpty(this.mod.user.listColumns)){
            this.mod.user.listColumns = cmpage.ui.listColumns.MAX;
        }
        let k =0;
        for (let col of this.modCols) {
            if (col.c_isshow) {
                k += 1;
                if(k &lt;= this.mod.user.listColumns) {
                    html.push(&#x60;&lt;th width=&quot;${col.c_width}&quot; style=&quot;text-align:center;&quot;&gt;${col.c_name} &lt;/th&gt;&#x60;);
                }
            }
        }
        if (this.mod.c_multiselect) {
            html.push(&#x27;&lt;th width=&quot;26&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;checkboxCtrl&quot; data-group=&quot;ids&quot; data-toggle=&quot;icheck&quot;&gt;&lt;/th&gt;&#x27;);
        }
        //if(this.mod.parmsUrl.readonly == 1) isShowBtns =false;
        if (isShowBtns) {
            html.push(&#x27;&lt;th width=&quot;100&quot; style=&quot;text-align:center;&quot;&gt;操作&lt;/th&gt;&#x27;);
        }
        html.push(&#x27;&lt;/tr&gt; &lt;/thead&gt;&#x27;);

        //数据列
        await this.getDataList();
        //    cmpage.debug(this.list.data);

        html.push(&#x27;&lt;tbody&gt;&#x27;);
        for (let item of this.list.data) {
            html.push(&#x60;&lt;tr id=&quot;row${item[this.pk]}&quot; data-id=&quot;${item[this.pk]}&quot; onclick=&quot;return pageRowSelect(${item[this.pk]},this);&quot; &gt;&#x60;);
            k =0;
            for (let col of this.modCols) {
                if (col.c_isshow) {
                    k += 1;
                    if(k &gt; this.mod.user.listColumns) {    break;             }
                        //                cmpage.debug(col);
                    html.push(&#x60;&lt;td style=&quot;${item[this.pk] === 0 ? &quot;font-weight:bold;&quot; + col.c_style : col.c_style}&quot; &gt;&#x60;);
                    if (item[this.pk] !== 0 ) {
                        if (!think.isEmpty(col.c_format)) {
                            if (col.c_coltype === &quot;decimal&quot;) {
                                html.push(cmpage.formatNumber(item[col.c_column], {pattern: col.c_format}));
                            } else if(col.c_coltype === &quot;timestamp&quot; || col.c_coltype === &quot;date&quot;) {
                                if(!think.isEmpty(item[col.c_column]))  html.push(cmpage.datetime(item[col.c_column], col.c_format));
                            }
                        } else if (col.c_type === &quot;checkbox&quot;) {
                            html.push(&#x60;&lt;input type=&quot;checkbox&quot;  data-toggle=&quot;icheck&quot; value=&quot;1&quot; disabled  ${item[col.c_column] || item[col.c_column]===1 ? &quot;checked&quot; : &quot;&quot;} /&gt;&#x60;);
                        } else if (!think.isEmpty(item[col.c_column]) &amp;&amp; col.c_type === &quot;replace&quot; &amp;&amp; !(/^select/.test(col.c_memo))) {
                            //类似： flow/act_assign:getLinkNameById:#c_type#
                            //debug(item,&#x27;page.htmlGetList - replace.item&#x27;);
                            let templete = cmpage.objPropertysReplaceToStr(col.c_memo, item);
                            html.push(await this.getReplaceText(item[col.c_column],templete));
                        } else if (col.c_type === &quot;html&quot;) {
                            let input = think.isEmpty(col.c_memo) ? item[col.c_column] : col.c_memo.replace(/#value#/ig,item[col.c_column]);
//                            debug(input,page.htmlGetList - input.html);
                            html.push(input);
                        } else {
                            if (!think.isEmpty(col.c_column)) {
                                html.push(item[col.c_column]);
                            }
                        }
                    }
                    html.push(&#x27;&lt;/td&gt;&#x27;)
                }
            }
            if (this.mod.c_multiselect) {
                html.push(&#x60;&lt;td&gt;&lt;input type=&quot;checkbox&quot; name=&quot;ids&quot; data-toggle=&quot;icheck&quot; value=&quot;${item[this.pk]}&quot;&gt;&lt;/td&gt;&#x60;);
            }
            if (isShowBtns) {
                html.push(&#x27;&lt;td &gt;&#x27;);
                let btnHtml =await this.htmlGetBtnList(item);
        //            cmpage.debug(btnHtml);
                html.push(btnHtml);
                html.push(&#x27;&lt;/td &gt;&#x27;);
            }
            html.push(&#x27;&lt;/tr &gt;&#x27;);
        }
        html.push(await this.htmlGetListSumRow(isShowBtns));  //合计
        html.push(&#x27;&lt;/tbody &gt;&#x27;);

        return html.join(&#x27; &#x27;);
    }

    /**
     * 是否显示列表中某行的某个按钮，子类中重写本方法可以改变行按钮显示的逻辑
     * 按钮设置的备注中，形如： {isShow:&#x27;#c_status#==1192 &amp;&amp; xxx&gt;xxx&#x27;}
     * @method  isShowBtn
     * @return {boolean} 是否显示
     */
    isShowBtn(rec,btn){
        if(!think.isEmpty(btn.c_memo)) {
            let sets = cmpage.objFromString(cmpage.objPropertysReplaceToStr(btn.c_memo, rec));
            if (!think.isEmpty(sets.isShow) &amp;&amp; !think.isEmpty(rec)) {
                //cmpage.debug(sets, &#x27;page.isShowBtn - sets&#x27;);
                //cmpage.debug(rec, &#x27;page.isShowBtn - rec&#x27;);
                return eval(&quot;(&quot; + sets.isShow + &quot;)&quot;);
            }
        }
//        if(btn.c_object.indexOf(&#x27;.View&#x27;) == -1 &amp;&amp; this.mod.c_modulename.indexOf(&#x27;Lookup&#x27;) &gt;0 )  return false;
        if(btn.c_object.indexOf(&#x27;.View&#x27;) == -1 &amp;&amp; this.mod.parmsUrl.readonly == 1)  return false;
        return true;
    }

    /**
     * 取结果数据集，子类中重写本方法可以增加逻辑如：对结果集做进一步的数据处理等
     * @method  getDataList
     * @return {object} 结果集数据包 {count:xxx, list:[{record}]}
     */
    async getDataList(){
        if(this.mod.user.listColumns === cmpage.ui.enumListColumns.MOBILE){
            this.mod.c_page_size = 8;
            this.mod.pageSize = 8;
        }
        let where=await this.getQueryWhere();
        //cmpage.debug(&#x60;select count(id) as count from ${this.mod.c_datasource} ${where} &#x60;);

        let cnt = await this.query(&#x60;select count(${this.pk}) as count from ${this.mod.c_datasource} ${where} &#x60;);
        //debug(cnt, &#x27;page.getDataList - cnt&#x27;);
        this.list.count = cnt[0].count;
        this.list.data = [];
        this.list.ids = [];
        if(this.list.count &gt;0 ) {
            //cmpage.debug(this.mod);
            let data = [];
            if (this.mod.c_pager) {
                let sql = &#x60;select ${this.getListFields(this.modCols)} from ${this.mod.c_datasource} ${where} order by ${this.mod.c_sort_by}
                    limit ${this.mod.c_page_size} offset ${this.mod.c_page_size * (this.mod.pageIndex - 1)}&#x60;;
                if(this.config.type == &#x27;mssql&#x27;){
                    let sortType = this.mod.c_sort_by.toLowerCase().indexOf(&#x27; desc&#x27;) == -1 ? 0 : 1;
                    let sortCol = this.mod.c_sort_by.toLowerCase().replace(/asc/g,&#x27;&#x27;).replace(/desc/g,&#x27;&#x27;);
                    sql = &#x60;QueryPage &#x27;${this.mod.c_datasource}&#x27;,&#x27;${this.getListFields(this.modCols)}&#x27;,${this.mod.pageSize},${this.mod.pageIndex},
                        &#x27;${where}&#x27;,&#x27;${sortCol}&#x27;,${sortType},&#x27;${this.pk}&#x27;&#x60;;
                }
                //debug(sql,&#x27;page.getDataList - sql&#x27;);
                data = await this.query(sql);
            } else {
                let limit = think.isEmpty(this.mod.c_data_limit) ? 2000 : this.mod.c_data_limit;
                let sql = &#x60;select ${this.getListFields()} from ${this.mod.c_datasource} ${where} order by ${this.mod.c_sort_by} limit ${limit}&#x60;;
                if(this.config.type == &#x27;mssql&#x27;){
                    sql = &#x60;select top ${limit} ${this.getListFields()} from ${this.mod.c_datasource} ${where} order by ${this.mod.c_sort_by} &#x60;;
                }
                data = await this.query(sql);
            }

            for (let rec of data) {
                if(data.indexOf(rec) == data.length -1 &amp;&amp; this.config.type==&#x27;mssql&#x27; &amp;&amp; this.mod.c_pager)    break;
                this.list.ids.push(rec[this.pk]);
                this.list.data.push(rec);
            }

        }
    }

    /**
     * 取合计行的HTML片段，子类中重写本方法可以定制合计行的显示
     * @method  isShowBtn
     * @return {string} 合计行的HTML片段
     */
    htmlGetListSumRow(isShowBtns){
        if(this.list.data.length &lt;=0)   return &#x27;&#x27;;
        let html = [];
        let isSum = false;
        for(let col of this.modCols){
            if(!col.c_isshow)   continue;
            if(col.c_type_sum == &#x27;none&#x27;){
                html.push(&#x27;&lt;td&gt; &lt;/td&gt;&#x27;);
            }else{
                isSum = true;
                if(col.c_type_sum == &#x27;text&#x27;){
                    html.push(&#x60;&lt;td style=&quot;text-align:center;font-weight:bold;&quot;&gt;${col.c_memo}&lt;/td&gt;&#x60;);
                    continue;
                }
                let sum = 0;
                for(let rec of this.list.data){
                    sum += rec[col.c_column];
                }
                if(col.c_type_sum == &#x27;avg&#x27;) sum = sum / this.list.data.length;
                html.push(&#x60;&lt;td style=&quot;text-align:right;font-weight:bold;&quot;&gt;${cmpage.formatNumber(sum,col.c_format)}&lt;/td&gt;&#x60;);
            }
        }
        if(isSum)   return &#x60;&lt;tr&gt;${html.join(&#x27;&#x27;)}${isShowBtns ? &#x27;&lt;td&gt; &lt;/td&gt;&#x27;:&#x27;&#x27; }&lt;/tr&gt;&#x60;;
        return &#x27;&#x27;;
    }

    /**
     * 取查询项的设置，结合POST参数，得到Where字句，重写本方法可以定制或修改SQL的where子句
     * @method  getQueryWhere
     * @return {string} where 子句， 形如： where xxx and xxx
     */
    async getQueryWhere(){
        let ret =[&#x27; where 1=1&#x27;];
        let parmsUrl =this.mod.parmsUrl;
        //debug(parmsUrl,&#x27;page.getQueryWhere - parmsUrl&#x27;);
        for(let md of this.modQuerys){
            if (md.c_type === &quot;fixed&quot;){         //如果是‘固定’，则直接增加c_memo中的设置值
                let wh = &#x60; (${md.c_memo.replace(/#userID#/,this.mod.user.id).replace(/#groupID#/,this.mod.user.groupID).split(/##/).join(&#x27;\&#x27;&#x27;)})&#x60;;
                if(wh.indexOf(&#x27;#value#&#x27;) &gt; -1 ){
                    wh =think.isEmpty(parmsUrl[md.c_column]) ? &#x27;&#x27; : wh.replace(/#value#/,parmsUrl[md.c_column]);
                }
                if(!think.isEmpty(wh)){
                    ret.push(wh);
                }
                continue;
            }
            if (md.c_isshow &amp;&amp; md.c_op!==&#x27;NO&#x27;) {
                if(!think.isEmpty(this.mod.query[md.c_column])){
                    if((md.c_coltype === &#x27;int&#x27; &amp;&amp; parseInt(this.mod.query[md.c_column])===0) || (md.c_type.indexOf(&#x27;select&#x27;) === 0 &amp;&amp; this.mod.query[md.c_column] == 0)){
                        continue;
                    }
                    //debug(md,&#x27;page.getQueryWhere - md&#x27;);
                    md.c_default = this.mod.query[md.c_column];
                    let value = this.mod.query[md.c_column].split(&#x27;\&#x27;&#x27;).join(&#x27; &#x27;).split(&#x27;\&quot;&#x27;).join(&#x27; &#x27;).trim();
                    value = cmpage.filterSensitiveString(value);
                    if(md.c_coltype ==&quot;bool&quot;)   value = think.isEmpty(value) ? 0:1;
                    if((md.c_column ===&#x27;c_province&#x27; || md.c_column ===&#x27;c_city&#x27; || md.c_column ===&#x27;c_country&#x27;)
                        &amp;&amp; (value ===&#x27;-1&#x27; || value === &#x27;&#x27;)){    continue;   }
                    ret.push(md.c_desc + &#x27; &#x27;+this.getOpValue(md.c_op, value, md.c_coltype));
                }
            }
        }
        return ret.join(&#x27; and &#x27;);
    }


  getOpValue(op,value,coltype){
  let ops = [ {op:&quot;EQ&quot;,val:&quot;= #value#&quot;},{op:&quot;NE&quot;,val:&quot;&lt;&gt; #value#&quot;},{op:&quot;CN&quot;,val:&quot;like #value#&quot;},{op:&quot;NC&quot;,val:&quot;not like #value#&quot;},{op:&quot;IN&quot;,val:&quot;in (#value#)&quot;},
    {op:&quot;NI&quot;,val:&quot;not in (#value#)&quot;},{op:&quot;GE&quot;,val:&quot;&gt;= #value#&quot;},{op:&quot;LE&quot;,val:&quot;&lt;= #value#&quot;},{op:&quot;GT&quot;,val:&quot;&gt; #value#&quot;},{op:&quot;LT&quot;,val:&quot;&lt; #value#&quot;}];
  let val = value;

  if (coltype === &quot;varchar&quot; || coltype === &quot;date&quot; || coltype === &quot;timestamp&quot;){
    if (op === &quot;CN&quot; || op === &quot;NC&quot;){
      val = &#x60;&#x27;%${val}%&#x27;&#x60;;
    }else if (op === &quot;IN&quot; || op === &quot;NI&quot;){//每项分别加单引号
      let str = val.Split(&#x27;,&#x27;);
      let sArr=[];
      for (let s of str){
        sArr.push(&#x60;&#x27;${s}&#x27;&#x60;);
      }
      val = sArr.join(&#x27;,&#x27;);
    }else{
      val = &#x60;&#x27;${val}&#x27;&#x60;;
    }
  }
  for (let operate of ops){
    if (operate.op === op){
      return operate.val.replace(/#value#/,val);
    }
  }
  return &quot;&quot;;
}

    /**
     * 根据设置取得页面显示列表返回的字段，一般不需要重写本方法
     * @method  getListFields
     * @return {string} fields 部分， 形如：id,c_name,xxx
     */
    getListFields(){
    let fields = [];
    for(let col of this.modCols){
      if (!col.c_isretrieve) continue;
      //if(col.c_column ===&#x27;c_user&#x27;){  console.log(col);}
      if (col.c_type === &quot;replace&quot; &amp;&amp; (col.c_isshow || col.c_isview) &amp;&amp; (col.c_memo.indexOf(&#x27;select&#x27;)===0)) //以select开头
      {
        fields.push(&#x60;(${col.c_memo}) as ${col.c_column}&#x60;);
      }else{
        fields.push(col.c_desc===col.c_column ? col.c_desc : &#x60;${col.c_desc} as ${col.c_column}&#x60;);
      }
    }

    //  cmpage.debug(fields);
    return fields.join(&#x27;,&#x27;);
  }

    /**
     * 新增的时候，初始化编辑页面的值，子类重写本方法可以定制新增页面的初始值
     * @method  pageEditInit
     * @return {object} 新增的记录对象
     */
    async pageEditInit(){
        let md ={};
        md.c_user = this.mod.user.id;
        md.c_group = this.mod.user.groupID;
        for(let edit of this.modEdits){
            let key = edit.c_column.trim();
            if([&#x27;c_user&#x27;,&#x27;c_group&#x27;].includes(key)){ continue; }
            //URL参数赋值
            if(!think.isEmpty(this.mod.parmsUrl[key])){
                md[key] = this.mod.parmsUrl[key];
                continue;
            }

            if(edit.c_coltype === &#x27;int&#x27; || edit.c_coltype === &#x27;float&#x27;) {
                md[key] = 0;
            }else if(edit.c_coltype === &#x27;bool&#x27;){
                md[key] = false;
            }else if(edit.c_coltype === &#x27;timestamp&#x27; ){
                md[key] = think.datetime();
            }else if(edit.c_coltype === &#x27;date&#x27;){
                md[key] = think.datetime(new Date, &quot;YYYY-MM-DD&quot;);
            }else {
                md[key] = &#x27;&#x27;;
            }
        }
        //如果有关联流程，则设置初始的 c_act, c_status
        if(!think.isEmpty(this.proc) &amp;&amp; this.proc.c_act_start &gt;0){
            debug(this.proc,&#x27;page.htmlGetBtnList - this.proc&#x27;);
            md.c_act = this.proc.c_act_start;
            let actStart = await cmpage.model(&#x27;flow/act&#x27;).getActById(this.proc.c_act_start);
            md.c_status = actStart.c_domain_st;
        }

        md[this.pk] =0;
        return md
    }

    /**
     * 取当前记录对象，用于新增和修改的编辑页面展示
     * @method  getDataRecord
     * @return {object} 当前记录对象
     */
    async getDataRecord(){
        let md = {};
        if(this.mod.editID &gt;0) {
            let fields = [];
            for (let edit of this.modEdits) {
                if(edit.c_desc.indexOf(&#x27;fn:&#x27;)!==0){
                    fields.push(&#x60;${edit.c_desc} as ${edit.c_column}&#x60;);
                }
            }
            let list = await this.model(this.mod.c_datasource).field(fields.join(&#x27;,&#x27;)).where(&#x60;${this.pk}=${this.mod.editID}&#x60;).select();
            md =list[0];
            // for(let p in md){   //去掉 null 值
            //     if(md[p] == &#x27;null&#x27;) md[p] = &#x27;&#x27;;
            // }
        }else{
            md = await this.pageEditInit();
        }
        //console.log(md);
        //对记录进行处理
        for (let edit of this.modEdits) {
            if(edit.c_coltype ===&#x27;bool&#x27;){
                md[edit.c_column] = think.isBoolean(md[edit.c_column]) ? md[edit.c_column] : (md[edit.c_column] === 1);
            }
        }
        this.rec = md;
        return md;
    }
    /**
     * 取编辑页面的设置，组合成列表数据的HTML输出
     * @method  htmlGetEdit
     * @return {string} HTML页面片段
     */
    async htmlGetEdit() {
        let html = [];
        let md = await this.getDataRecord();
        //debug(md,&#x27;page.htmlGetEdit - md&#x27;);
        if(think.isEmpty(md))   return &#x27;&#x27;;
        //子类中可以重写此处之前涉及的方法来改变URL参数值等，例如 getDataRecord， 参见 docu/docu_list
        if(this.mod.parmsUrl.readonly){
            this.modCols = await cmpage.model(&#x27;cmpage/module&#x27;).getModuleCol(this.mod.id);
            //debug(this.mod,&#x27;page.htmlGetEdit - this.mod&#x27;);
            return &#x60;&lt;table id=&quot;pageViewData&quot; class=&quot;table table-condensed table-hover&quot; width=&quot;100%&quot;&gt;&lt;tbody&gt;${await this.htmlGetView()}&lt;/tbody&gt; &lt;/table&gt; &#x60;;
        }
        //html.push(&#x60;&lt;div id=&quot;edit${this.mod.c_modulename}Table&quot; class=&quot;bjui-row col-${this.mod.c_edit_column}&quot;&gt;&#x60;);
        this.mod.editHeaderHtml = think.isEmpty(this.mod.c_other.editTitle) ? &#x27;&#x27; : &#x60;&lt;div class=&quot;bjui-pageHeader&quot;&gt;
                &lt;label data-height=&quot;30px&quot; style=&quot;margin: 5px;&quot;&gt;${this.mod.c_other.editTitle}&lt;/label&gt;&lt;/div&gt;&#x60;;

        html.push(&#x60;&lt;input name=&#x27;old_record&#x27; type=&#x27;hidden&#x27; value=&#x27;${JSON.stringify(md).replace(/\&#x27;/g,&#x27;&#x27;)}&#x27; /&gt;&#x60;);
//        cmpage.debug(md);
        for(let col of this.modEdits){
            if (!col.c_editable || col.c_column === this.pk ) {  continue; }
            let colValue = md[col.c_column];
            if(col.c_desc.indexOf(&#x27;fn:&#x27;)===0){    //非数据库字段
                let its = col.c_desc.trim().split(&#x27;:&#x27;);        //设置如： fn:admin/code:getNameByPid:c_status
                let fnModel = cmpage.model(its[1]);     //通过某个模块的某个方法取下拉设置
                if(think.isFunction(fnModel[its[2]])){
                    if(its.length === 4){
                        colValue = await fnModel[ its[2] ]( md[its[3]]);
                    }else{
                        colValue = await fnModel[ its[2] ]();
                    }
                }
                debug(colValue,&#x27;page.htmlGetEdit.fn - colValue&#x27;);
            }

            if(col.c_coltype === &#x27;timestamp&#x27;){  colValue = think.datetime(colValue); }
            if (col.c_type === &quot;hidden&quot; &amp;&amp; col.c_column!==&quot;c_city&quot; &amp;&amp; col.c_column!==&quot;c_province&quot;) {
                html.push(&#x60;&lt;input id=&quot;${this.mod.c_modulename + col.c_column}&quot; name=&quot;${col.c_column}&quot; type=&quot;hidden&quot; value=&quot;${colValue}&quot; /&gt;&#x60;);
                continue;
            }
            col.c_format = col.c_format.trim();
            col.c_width = this.mod.user.listColumns === cmpage.ui.enumListColumns.MOBILE ? 20 : col.c_width;
            if(col.c_type !== &quot;hidden&quot;){
                html.push(&#x60; &lt;label  class=&quot;row-label&quot; &gt;${col.c_name}: &lt;/label&gt;&#x60;);
            }
            let input =&#x27;&#x27;;
            if (col.c_type === &quot;datetime&quot; ||col.c_type === &quot;date&quot;) {
                input += &#x60;&lt;input type=&quot;text&quot; id=&quot;${this.mod.c_modulename + col.c_column}&quot; name=&quot;${col.c_column}&quot; value=&quot;${ cmpage.datetime(colValue,think.isEmpty(col.c_format) ? &#x27;yyyy-MM-dd&#x27;:col.c_format)}&quot;
                    ${col.c_type === &quot;readonly&quot; ? &quot;disabled&quot;:&quot;&quot;} data-toggle=&quot;datepicker&quot; data-pattern=&quot;${think.isEmpty(col.c_format) ? &#x27;yyyy-MM-dd&#x27;:col.c_format}&quot;  size=&quot;15&quot; /&gt;&#x60;;
            } else if (col.c_type === &quot;select&quot; || col.c_type === &quot;selectBlank&quot; ) {
                input += &#x60;&lt;select id=&quot;${this.mod.c_modulename + col.c_column}&quot; name=&quot;${col.c_column}&quot; data-toggle=&quot;selectpicker&quot; ${col.c_isrequired ? &quot;data-rule=required&quot; : &quot;&quot;}&gt;&#x60;;
                col.c_default = colValue;
                input += await this.getOptions(col,false);
                input += &#x27;&lt;/select&gt;&#x27;;
            } else if (col.c_type === &quot;selectTree&quot; || col.c_type === &quot;selectTreeMultiple&quot;) {
                col.c_default = colValue;
                let treeOptions = await this.getOptionsTree(col,false);
                input += &#x60;&lt;input id=&quot;${this.mod.c_modulename + col.c_column}&quot; name=&quot;${col.c_column}&quot;  type=&quot;hidden&quot; value=&quot;${colValue}&quot; /&gt;
                    &lt;input name=&quot;${col.c_column}Show&quot; type=&quot;text&quot; size=&quot;25&quot; value=&quot;${treeOptions.selectName}&quot; data-toggle=&quot;selectztree&quot; data-tree=&quot;#selectTree${this.mod.c_modulename + col.c_column}&quot;   readonly /&gt;
                    &lt;ul id=&quot;selectTree${this.mod.c_modulename + col.c_column}&quot; class=&quot;ztree hide&quot; data-toggle=&quot;ztree&quot; data-expand-all=&quot;false&quot; data-check-enable=&quot;true&quot;
                    data-value-input=&quot;${this.mod.c_modulename + col.c_column}&quot; ${(col.c_type === &quot;selectTree&quot; ? &#x27; data-chk-style=&quot;radio&quot; data-radio-type=&quot;all&quot; &#x27;:&#x27; &#x27;)}
                    data-on-check=&quot;selectNodeCheck&quot; data-on-click=&quot;selectNodeClick&quot; &gt; ${treeOptions.options} &lt;/ul&gt;&#x60;;
            } else if (col.c_type === &quot;textarea&quot;) {
                let options = cmpage.objFromString(col.c_memo);
                input += &#x60;&lt;textarea id=&quot;${this.mod.c_modulename + col.c_column}&quot; name=&quot;${col.c_column}&quot; data-toggle=&quot;autoheight&quot; cols=&quot;${col.c_width}&quot;
                    rows=&quot;${options.row || 1}&quot;  ${col.c_isrequired ? &quot;data-rule=required&quot; : &quot;&quot;}&gt;${colValue}&lt;/textarea&gt;&#x60;;
            } else if (col.c_type === &quot;lookup&quot;) {
                input += &#x60;&lt;input id=&quot;${this.mod.c_modulename + col.c_column}&quot; name=&quot;${col.c_column}&quot; type=&quot;lookup&quot; size=&quot;10&quot; value=&quot;${colValue}&quot;
                    data-width=&quot;800&quot; data-height=&quot;600&quot; data-toggle=&quot;lookup&quot; data-title=&quot;${col.c_name} 选择&quot; data-url=&quot;${this.getReplaceToSpecialChar(col.c_memo)}&quot; readonly=&quot;readonly&quot; /&gt;
                      &lt;!--&lt;a class=&quot;bjui-lookup&quot; href=&quot;javascript:;&quot; &gt;&lt;i class=&quot;fa fa-search&quot;&gt;&lt;/i&gt;&lt;/a&gt;--&gt; &#x60;;
            } else if (col.c_type === &quot;fileUpload&quot;) {
                let options = {       pick: {label: &#x27;点击选择文件&#x27;},
                                      server: &#x27;/cmpage/page/upload_file&#x27;,
                                      fileNumLimit: 1,
                                      fileSingleSizeLimit: 1024*1024*5,
                                      formData: {link_type:this.mod.c_table,inputName:col.c_column},
                                      required: col.c_isrequired,
                                      uploaded: &#x27;&#x27;,
                                      basePath: &#x27;&#x27;,
                                      accept: {
                                          title: &#x27;文件&#x27;,
                                          extensions: this.mod.parmsUrl.c_type==0 ? &#x27;*&#x27;: &#x27;jpg,png,jpeg,gif,bmp&#x27;,
                                          mimeTypes: this.mod.parmsUrl.c_type==0 ? &#x27;.*&#x27;: &#x27;.jpg,.png,.jpeg,.gif,.bmp&#x27;
                                      }
                                };
              input += &#x60;&lt;input type=&quot;file&quot; name=&quot;${col.c_column}&quot; data-name=&quot;${col.c_column}&quot; data-toggle=&quot;webuploader&quot; data-options=&quot;${cmpage.objToString(options)}&quot; &gt;&#x60;;
            }else if (col.c_type == &quot;areaSelect&quot;){
                input += &#x60;&lt;select name=&quot;c_province&quot; data-toggle=&quot;selectpicker&quot;  data-nextselect=&quot;#city${this.mod.c_modulename}&quot; data-refurl=&quot;/cmpage/utils/get_citys?province={value}&quot; &gt;&#x60;;
                input += await cmpage.model(&#x27;cmpage/area&#x27;).getProvinceItems(md[&#x27;c_province&#x27;],true);
                if(col.c_column ===&#x27;c_country&#x27;){
                    input += &#x60;&lt;/select&gt; &lt;select name=&quot;c_city&quot; id=&quot;city${this.mod.c_modulename}&quot; data-toggle=&quot;selectpicker&quot; data-nextselect=&quot;#country${this.mod.c_modulename}&quot;
                        data-refurl=&quot;/cmpage/utils/get_countrys?city={value}&quot; &gt;&#x60;;
                    input += await cmpage.model(&#x27;cmpage/area&#x27;).getCityItems(md[&#x27;c_city&#x27;],true);
                    input += &#x60;&lt;/select&gt; &lt;select name=&quot;c_country&quot; id=&quot;country${this.mod.c_modulename}&quot; data-toggle=&quot;selectpicker&quot; data-rule=&quot;required&quot; &gt;&#x60;;
                    input += await cmpage.model(&#x27;cmpage/area&#x27;).getCountryItems(md[&#x27;c_country&#x27;],true);
                }else if(col.c_column === &#x27;c_city&#x27;){
                    input += &#x60;&lt;/select&gt; &lt;select name=&quot;c_city&quot; id=&quot;city${this.mod.c_modulename}&quot; data-toggle=&quot;selectpicker&quot; data-nextselect=&quot;#country${this.mod.c_modulename}&quot; &gt;&#x60;;
                    input += await cmpage.model(&#x27;cmpage/area&#x27;).getCityItems(md[&#x27;c_city&#x27;],true);
                }
                input += &#x27;&lt;/select&gt;&#x27;;
            } else if(col.c_type === &quot;kindeditor&quot;){
                input += &#x60;&lt;div style=&quot;display: inline-block; vertical-align: middle;&quot;&gt; &lt;textarea name=&quot;${col.c_column}&quot; style=&quot;width: 960px;height:640px;&quot;
                        data-toggle=&quot;kindeditor&quot; data-minheight=&quot;460&quot;&gt; ${colValue}  &lt;/textarea&gt; &lt;/div&gt;&#x60;;
            } else if (col.c_type == &quot;checkbox&quot;) {
                input += &#x60;&lt;input id=&quot;${this.mod.c_modulename + col.c_column}&quot; type=&quot;checkbox&quot; name=&quot;${col.c_column}&quot; data-toggle=&quot;icheck&quot; value=&quot;1&quot; data-label=&quot;${col.c_memo}&quot;
                    ${colValue == &quot;1&quot; ? &quot;checked&quot; : &quot;&quot;} /&gt;&#x60;;
            // }else if (col.c_type === &quot;readonly&quot;) {
            //     input += &#x60;&lt;input id=&quot;${this.mod.c_modulename + col.c_column}&quot; name=&quot;${col.c_column}&quot; type=&quot;text&quot; size=&quot;${col.c_width}&quot; value=&quot;${colValue}&quot;  readonly=&quot;readonly&quot;  /&gt;&#x60;; // style=background-color:#fde5d4;
            }else if (col.c_type === &quot;readonly&quot;) {      //readonly 和 readonlyReplace 类型合并
                //debug(col,&#x27;page.htmlGetEdit - col readonlyReplace&#x27;);
//                debug(md,&#x27;this.mod.getHtmlEdit --- md readonlyReplace&#x27;);
                if(think.isEmpty(col.c_memo)){
                    input += &#x60;&lt;input id=&quot;${this.mod.c_modulename + col.c_column}&quot; name=&quot;${col.c_column}&quot; type=&quot;text&quot; size=&quot;${col.c_width}&quot; value=&quot;${colValue}&quot;  readonly=&quot;readonly&quot;  /&gt;&#x60;; // style=background-color:#fde5d4
                }else{
                    let txt = await this.getReplaceText(colValue, col.c_memo);
                    //debug(txt+&#x27; - value:&#x27;+colValue,&#x27;page.htmlGetEdit - txt,colValue readonlyReplace&#x27;);
                    input += &#x60;&lt;input name=&quot;${col.c_column}&quot; type=&quot;hidden&quot;  value=&quot;${colValue}&quot;  readonly=&quot;readonly&quot;  /&gt;&#x60;;
                    input += &#x60;&lt;input name=&quot;${col.c_column}_text&quot; type=&quot;text&quot; size=&quot;${col.c_width}&quot; value=&quot;${txt}&quot;  readonly=&quot;readonly&quot;  /&gt;&#x60;; // style=background-color:#fde5d4;
                }
            }else if(col.c_column !==&#x27;c_province&#x27; &amp;&amp; col.c_column !==&#x27;c_city&#x27;){
                input += &#x60;&lt;input id=&quot;${this.mod.c_modulename + col.c_column}&quot; name=&quot;${col.c_column}&quot; type=&quot;${col.c_type}&quot; size=&quot;${col.c_width}&quot; value=&quot;${colValue}&quot;
                    ${col.c_isrequired ? &quot;data-rule=required;&quot; + col.c_memo : (think.isEmpty(col.c_memo) ? &quot;&quot; : &quot;data-rule=&quot; + col.c_memo)} /&gt;&#x60;;
            }
            if (col.c_type !== &quot;areaSelect&quot;){
                input += col.c_suffix;
            }
            if(input.length &gt;0){
                input = await this.htmlGetEditInput(col,colValue,input);
                html.push(input);
            }

        }
        return &#x60;&lt;div id=&quot;edit${this.mod.c_modulename}Table&quot; class=&quot;bjui-row col-${this.mod.c_edit_column}&quot;&gt;${html.join(&#x27;&#x27;)}&lt;/div&gt;&#x60;;
    }

    /**
     * 改变某些编辑列的样式，子类中可以重写本方法类增加模块编辑页面的操作逻辑
     * @method  htmlGetEditInput
     * @return {string} Edit页面的Input的HTML片段
     * @params {object} col Edit页面的当前编辑列设置
     * @params {string} colValue Input的值
     * @params {string} input Edit页面的Input的HTML片段
     */
    async htmlGetEditInput(col,colValue,input) {
        let html = &#x60;&lt;div id=&quot;field${this.mod.c_modulename + col.c_column}&quot;  class=&quot;row-input&quot;&gt;${input}&lt;/div&gt;&#x60;;
        //增加模块编辑页面的操作逻辑，也可以配合页面js方法

        return html;
    }

    /**
     * 取编辑页面的按钮设置，组合按钮的HTML输出
     * @method  htmlGetEditBtns
     * @return {string} HTML页面片段
     */
    async htmlGetEditBtns() {
        //cmpage.debug(this.mod,&#x27;page.htmlGetEditBtns -- this.mod&#x27;)
        let html = [];
        let parmsUrl = this.mod.parmsUrl;

        if(think.isEmpty(this.mod.c_other.editHideCloseBtn)){
            html.push(&#x27;&lt;li&gt;&lt;button type=&quot;button&quot; class=&quot;btn-close&quot; data-icon=&quot;close&quot;&gt;关闭&lt;/button&gt;&lt;/li&gt;&#x27;);
        }
        //debug(task,&#x27;page.htmlGetEditBtns - task&#x27;);
        let defaultSaveBtn = &#x27;&lt;li &gt;&lt;button type=&quot;submit&quot; class=&quot;btn-green&quot;  data-icon=&quot;save&quot;&gt;保存&lt;/button&gt;&lt;/li&gt;&#x27;;
        if(!think.isEmpty(this.mod.c_module_slave.modulename)){
            let reloadUrl = &#x60;/cmpage/page/edit_ms?modulename=${this.mod.c_modulename}&amp;listIds=&#x60;;
            for(let p in this.mod.parmsUrl){
                //加入URL参数
                if(![&#x27;modulename&#x27;,this.pk,&#x27;listIds&#x27;,&#x27;_&#x27;].includes(p)){
                    reloadUrl += &#x60;&amp;${p}=${this.mod.parmsUrl[p]}&#x60;;
                }
            }
            defaultSaveBtn = &#x60;&lt;li &gt;&lt;button type=&quot;button&quot; class=&quot;btn-green&quot; onclick=&quot;return pageSaveMs(&#x27;${this.mod.c_modulename}&#x27;,&#x27;${reloadUrl}&#x27;,
                ${this.mod.editID},&#x27;${this.pk}&#x27;);&quot;  data-icon=&quot;save&quot;&gt;保存&lt;/button&gt;&lt;/li&gt;&#x60;;
        }
        debug(defaultSaveBtn,&#x27;page.htmlGetEditBtns - defaultSaveBtn&#x27;);
        if(think.isEmpty(this.mod.c_other.editHideSaveBtn) &amp;&amp; !this.mod.parmsUrl.readonly &amp;&amp; !this.rec.hasOwnProperty(&#x27;c_task&#x27;) ) {
            html.push(defaultSaveBtn);
        }
        debug(this.rec,&#x27;page.htmlGetEditBtns - this.rec&#x27;);
        if(!think.isEmpty(this.rec[&#x27;c_task&#x27;]) &amp;&amp; this.rec.c_task &gt;0){
            let task =  await cmpage.model(&#x27;flow/task&#x27;).getTask(this.rec.c_task &gt; 0 ? this.rec.c_task: parmsUrl.taskID);
            //debug(task,&#x27;page.htmlGetEditBtns - task&#x27;);
            if(task.c_link_type === this.mod.c_table){
                if(think.isEmpty(parmsUrl.taskActID)){
                    html.push(defaultSaveBtn);
                }else{
                    let reloadUrl = &#x60;/cmpage/page/edit?modulename=${this.mod.c_modulename}&amp;taskActID=${parmsUrl.taskActID}&amp;status=${parmsUrl.status}&amp;listIds=&#x60;;
                    html.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;btn-green&quot;  data-icon=&quot;save&quot;
                            onclick=&quot;return pageSaveByTask(&#x27;${this.mod.c_modulename}&#x27;,&#x27;${reloadUrl}&#x27;,
                            &#x27;${think.isEmpty(this.mod.c_other.editSaveAfter) ? &#x27;&#x27; : this.mod.c_other.editSaveAfter}&#x27;);&quot;&gt;
                            ${think.isEmpty(this.mod.c_other.editSaveLabel) ? &#x27;保存&#x27; : this.mod.c_other.editSaveLabel}&lt;/button&gt;&#x60;);
                    // html.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;btn-green&quot;  data-icon=&quot;save&quot;
                    //         onclick=&quot;return pageSaveByTask(&#x27;${this.mod.c_modulename}&#x27;,${parmsUrl.taskActID},${parmsUrl.status},
                    //         &#x27;${think.isEmpty(this.mod.c_other.editSaveAfter) ? &#x27;&#x27; : this.mod.c_other.editSaveAfter}&#x27;);&quot;&gt;
                    //         ${think.isEmpty(this.mod.c_other.editSaveLabel) ? &#x27;保存&#x27; : this.mod.c_other.editSaveLabel}&lt;/button&gt;&#x60;);
                }
            }
        }

        if(this.mod.editID &gt;0 &amp;&amp; think.isEmpty(this.mod.c_module_slave.modulename)) {
            let listIds = parmsUrl.listIds.split(&#x27;,&#x27;);
            if (listIds.length &gt; 0) {
                let prevID = 0, nextID = 0;
                let k = 0;
                for (let id of listIds) {
                    if (id == this.mod.editID) {
                        k = listIds.indexOf(id);
                        break;
                    }
                }
                if (k &gt; 0) {
                    prevID = listIds[k - 1];
                }
                if (k &lt; listIds.length - 1) {
                    nextID = listIds[k + 1];
                }
                html.push(&#x60;&lt;li class=&quot;left&quot; style=&quot;margin-left: -40px;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn-default&quot; ${k == 0 ? &#x27;style=&quot;display:none&quot;&#x27; : &#x27;&#x27;} data-icon=&quot;arrow-left&quot;
                        onclick=&quot;return pageGotoEdit(&#x27;${this.mod.c_modulename}&#x27;,${prevID});&quot;&gt;上一条&lt;/button&gt;&lt;/li&gt;&#x60;);
                html.push(&#x60;&lt;li class=&quot;left&quot; &gt;&lt;button type=&quot;button&quot; class=&quot;btn-default&quot; ${nextID == 0 ? &#x27;style=&quot;display:none&quot;&#x27; : &#x27;&#x27;} data-icon=&quot;arrow-right&quot;
                        onclick=&quot;return pageGotoEdit(&#x27;${this.mod.c_modulename}&#x27;,${nextID});&quot;&gt;下一条&lt;/button&gt;&lt;/li&gt;&#x60;);
            }
        }
        //如果和流程相关，则显示流程节点的按钮
        if(!think.isEmpty(this.proc)){
            //debug(this.proc,&#x27;page.htmlGetBtnList - this.proc&#x27;);
            let actBtns = [];
            if(this.proc.c_type === cmpage.enumProcType.STATUSCHANGE){
                //直接取模板设置的按钮
                if(this.rec.c_act &gt; 0 ){
                    actBtns = await this.htmlGetActBtns(this.rec);
                }
            }else{
                //取当前任务节点的模板设置的按钮
                if(this.rec.c_task &gt; 0 ){
                    actBtns = await this.htmlGetTaskActBtns(this.rec);
                }
            }
            for(let btn of actBtns){
                btn = &#x60;&lt;li class=&quot;left&quot; &gt;${btn}&lt;/li&gt;&#x60;;
            }
            if(!think.isEmpty(actBtns))  html.push(actBtns.join(&#x27;&#x27;));
        }

        return html.join(&#x27;&#x27;);
    }
    /**
    * 取状态流转类型的流程节点相关的按钮设置，组合成按钮的HTML输出&lt;/br&gt;
    * 考虑到按钮输出和业务关联度大，定义在此处
     * @method  htmlGetActBtns
     * @return {Array} 按钮数组
     */
    async htmlGetActBtns(rec) {
        let html = [];
        //debug(rec,&#x27;page.htmlGetActBtns - rec&#x27;);
        let actModel = cmpage.model(&#x27;flow/act&#x27;);
        let act = await actModel.getActById(rec.c_act);
        if(think.isEmpty(act)){    return []; }

        //debug(act,&#x27;page.htmlGetActBtns - act&#x27;);

        let form = think.isEmpty(act.c_form) ? {} : cmpage.objFromString(act.c_form);
        //debug(form,&#x27;page.htmlGetActBtns - form&#x27;);

        let createUserID = think.isEmpty(rec.c_creater) ? 0 : rec.c_creater;
        //如果主业务模块实现类已经定义了 getStatusById方法，则调用，否则，直接从数据库中取业务记录状态
        //如果主业务模块操作的数据表位于和框架不同的数据库，则需要定义 getStatusById 方法
        //debug(this.proc,&#x27;page.htmlGetActBtns - this.proc&#x27;);
        let linkRec ={};
        linkRec.id = think.isEmpty(this.mod.parmsUrl.linkID) ? rec[this.pk] : this.mod.parmsUrl.linkID;
        let linkModel = cmpage.model(this.proc.c_link_model);
        linkModel.mod = await cmpage.model(&#x27;cmpage/module&#x27;).getModuleByName(this.proc.linkModulename);
        await linkModel.initPage();
        if(think.isEmpty(linkModel[&#x27;getStatusById&#x27;])){
            linkRec = await linkModel.model(this.proc.c_link_type).where(&#x60;${linkModel.pk}=${linkRec.id}&#x60;).find();
        }else{
            linkRec = await linkModel.getStatusById(linkRec.id);
        }
        linkRec.id = think.isEmpty(this.mod.parmsUrl.linkID) ? rec[this.pk] : this.mod.parmsUrl.linkID;
        debug(linkRec,&#x27;page.htmlGetActBtns - linkRec&#x27;);
        debug(act,&#x27;page.htmlGetTaskActBtns - act&#x27;);

        //debug(task,&#x27;page.htmlGetTaskActBtns - task&#x27;);
        if(act.id &gt;0){
            //debug(form,&#x27;page.htmlGetActBtns - form&#x27;);
            //if(form.hasOwnProperty(&#x27;modulename&#x27;) &amp;&amp; form[&#x27;modulename&#x27;] == this.mod.c_modulename ){
            if(linkRec.c_status != act.c_domain_st){
                //debug(linkRec,&#x27;page.htmlGetActBtns - linkRec&#x27;);
                //验证当前用户是否有该节点的权限
                let actAssign = await cmpage.model(&#x27;flow/act_assign&#x27;).getAssignByUser(act.id,this.mod.user, createUserID);
                debug(actAssign,&#x27;page.htmlGetActBtns - actAssign&#x27;);
                if(think.isEmpty(actAssign))   return [];

                //本表单是流程节点需要打开的表单
                let btns = cmpage.arrFromString(act.c_form_btn);
                for(let btn of btns){
                    btn.label = think.isEmpty(btn[&#x27;label&#x27;]) ? act.c_name : btn.label;
                    btn.class = think.isEmpty(btn[&#x27;class&#x27;]) ? &#x27;btn-green&#x27; : btn.class;
                    btn.icon = think.isEmpty(btn[&#x27;icon&#x27;]) ? &#x27;cogs&#x27; : btn.icon;
                    if(!think.isEmpty(btn[&#x27;onclick&#x27;])){
                        btn.onclick = btn.onclick.replace(/#procID#/g,this.proc.id).replace(/#actID#/g,act.id);
                        html.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;${btn.class}&quot; data-icon=&quot;${btn.icon}&quot; onclick=&quot;${btn.onclick}&quot;&gt;${btn.label}&lt;/button&gt;&#x60;);
                    }
                    else if(!think.isEmpty(btn[&#x27;url&#x27;])){
                        btn.title = think.isEmpty(btn[&#x27;title&#x27;]) ? btn.label : btn.title;
                        btn.opentype = think.isEmpty(btn[&#x27;opentype&#x27;]) ? &#x27;dialog&#x27; : btn.opentype;
                        btn.url = btn.url.replace(/#procID#/g,this.proc.id).replace(/#actID#/g,act.id);
                        html.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;${btn.class}&quot; data-icon=&quot;${btn.icon}&quot; data-toggle=&quot;${btn.opentype}&quot;
                            data-options=&quot;{id:&#x27;flowDialog&#x27;, url:&#x27;${btn.url}&#x27;, title:&#x27;${btn.title}&#x27;}&quot;&gt;${btn.label}&lt;/button&gt;&#x60;);
                    }else {
                        html.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;${btn.class}&quot; data-icon=&quot;${btn.icon}&quot; data-toggle=&quot;doajax&quot;
                            data-options=&quot;{url:&#x27;/cmpage/page/update_status?modulename=${this.mod.c_modulename}&amp;id=${rec[this.pk]}&amp;actID=${act.id}&amp;status=${act.c_domain_st}&#x27;,
                            confirmMsg:&#x27;是否确定要${btn.label}？&#x27;}&quot;&gt;${btn.label}&lt;/button&gt;&#x60;);
                    }
                }
                // debug(linkRec,&#x27;page.htmlGetActBtns - linkRec&#x27;);
                // debug(this.mod,&#x27;page.htmlGetActBtns - this.mod&#x27;);
                // debug(this.proc,&#x27;page.htmlGetActBtns - this.proc&#x27;);
                if (linkRec.id &gt;0 &amp;&amp; this.proc.c_link_type != this.mod.c_table) {
                    if(linkRec.c_status == act.c_domain_st) {
                        html.push(&#x27;&lt;label style=&quot;color: red;&quot;&gt;本操作已经执行完毕！&lt;/label&gt;&#x27;);
                    }else{
                        //默认的保存或者审核通过按钮
                        let reloadUrl = &#x60;/cmpage/page/${think.isEmpty(this.mod.c_module_slave.modulename) ? &#x27;edit&#x27;:&#x27;edit_ms&#x27;}?modulename=${this.mod.c_modulename}&amp;procID=${
                            this.proc.id}&amp;actID=${act.id}&amp;status=${act.c_domain_st}&amp;linkID=${linkRec.id}&amp;linkType=${this.proc.c_link_type}&amp;linkModel=${this.proc.c_link_model}&amp;listIds=&#x60;;
                        debug(reloadUrl,&#x27;page.htmlGetActBtns - reloadUrl&#x27;);
                        html.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;btn-green&quot;  data-icon=&quot;save&quot;
                            onclick=&quot;return pageSaveByAct(&#x27;${this.mod.c_modulename}&#x27;,&#x27;${reloadUrl}&#x27;,
                            &#x27;${think.isEmpty(this.mod.c_other.editSaveAfter) ? &#x27;&#x27; : this.mod.c_other.editSaveAfter}&#x27;);&quot;&gt;
                            ${think.isEmpty(this.mod.c_other.editSaveLabel) ? &#x27;保存&#x27; : this.mod.c_other.editSaveLabel}&lt;/button&gt;&#x60;);
                    }
                }
            }else if(this.proc.c_link_type == this.mod.c_table){
                //本表单是流程的关联主表单，则显示本流程节点的调用按钮
                //找到当前节点去向节点，并显示调用该节点的按钮，可能有多个去向
                let toActs = await cmpage.model(&#x27;flow/act&#x27;).getToActsFromId(this.proc.id, act.id);
                //debug(toActs,&#x27;page.htmlGetActBtns - toActs&#x27;);
                for(let toAct of toActs){
                    //验证当前用户是否有该节点的权限
                    let actAssign = await cmpage.model(&#x27;flow/act_assign&#x27;).getAssignByUser(toAct.id,this.mod.user, createUserID);
                    //debug(actAssign,&#x27;page.htmlGetActBtns - actAssign&#x27;);
                    if(think.isEmpty(actAssign))   continue;

                    let btn = think.isEmpty(toAct.c_call_btn) ? {}:eval(&#x60;(${toAct.c_call_btn})&#x60;);
                    btn.label = think.isEmpty(btn[&#x27;label&#x27;]) ? toAct.c_name : btn.label;
                    btn.class = think.isEmpty(btn[&#x27;class&#x27;]) ? &#x27;btn-green&#x27; : btn.class;
                    btn.icon = think.isEmpty(btn[&#x27;icon&#x27;]) ? &#x27;cogs&#x27; : btn.icon;
                    let form = think.isEmpty(toAct.c_form) ? {} : eval(&quot;(&quot;+ toAct.c_form +&quot;)&quot;);
                    form.title = think.isEmpty(btn[&#x27;title&#x27;]) ? btn.label : btn.title;
                    form.opentype = think.isEmpty(btn[&#x27;opentype&#x27;]) ? &#x27;dialog&#x27; : btn.opentype;
                    if(think.isEmpty(toAct.c_form)){
                        //默认是业务主模块，则修改本身状态
                        html.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;${btn.class}&quot; data-icon=&quot;${btn.icon}&quot; data-toggle=&quot;doajax&quot;
                            data-options=&quot;{url:&#x27;/cmpage/page/update_status?modulename=${this.mod.c_modulename}&amp;id=${rec[this.pk]}&amp;actID=${toAct.id}&amp;status=${toAct.c_domain_st}&#x27;,
                            confirmMsg:&#x27;是否确定要${btn.label}？&#x27;}&quot;&gt;${btn.label}&lt;/button&gt;&#x60;);
                    }else{
                        if(!think.isEmpty(form[&#x27;modulename&#x27;])){
                            //如果被调用节点对应 form.modulename 也是业务主模块，则修改本身状态
                            if(form.modulename === this.mod.c_modulename){
                                html.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;${btn.class}&quot; data-icon=&quot;${btn.icon}&quot; data-toggle=&quot;doajax&quot;
                                    data-options=&quot;{url:&#x27;/cmpage/page/update_status?modulename=${this.mod.c_modulename}&amp;id=${rec[this.pk]}&amp;actID=${toAct.id}&amp;status=${toAct.c_domain_st}&#x27;,
                                    confirmMsg:&#x27;是否确定要${btn.label}？&#x27;}&quot;&gt;${btn.label}&lt;/button&gt;&#x60;);
                                continue;
                            }else{
                                form.url = &#x60;/cmpage/page/edit?modulename=${form[&#x27;modulename&#x27;]}&amp;id=0&amp;procID=${toAct.c_proc}&amp;actID=${toAct.id}&amp;status=${toAct.c_domain_st}&amp;linkID=${rec[this.pk]}&amp;linkType=${this.mod.c_table}&amp;linkModulename=${this.mod.c_modulename}&#x60;;
                            }
                        }
                        form.url = form.url.replace(/#actID#/g,toAct.id);
                        html.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;${btn.class}&quot; data-icon=&quot;${btn.icon}&quot; data-toggle=&quot;${form.opentype}&quot;
                                data-options=&quot;{id:&#x27;flowDialog&#x27;, url:&#x27;${form.url}&#x27;, title:&#x27;${form.title}&#x27;, mask:true}&quot;&gt;${btn.label}&lt;/button&gt;&#x60;)
                    }
                }
            }
        }

        return html;
    }

    /**
     * 取流程节点相关的按钮设置，组合按钮的HTML输出&lt;/br&gt;
     * 考虑到按钮输出和业务关联度大，定义在此处
     * @method  htmlGetTaskActBtns
     * @return {Array} 按钮数组
     */
    async htmlGetTaskActBtns(rec) {
        let html = [];
        //debug(rec,&#x27;page.htmlGetTaskActBtns - rec&#x27;);
        let task = await cmpage.model(&#x27;flow/task&#x27;).getTask(rec.c_task);
        if(think.isEmpty(task)){    return []; }

        let parmsUrl = this.mod.parmsUrl;
        //取流程的当前节点，然后取按钮设置
        let act ={},taskAct={};
        if(think.isEmpty(parmsUrl[&#x27;taskActID&#x27;])){
            let taskModel = cmpage.model(&#x27;flow/task&#x27;);
            act =await taskModel.getTaskWithCurrentAct(task);
            taskAct = taskModel.currTaskAct;
        }else{
            taskAct = await cmpage.model(&#x27;flow/task_act&#x27;).getTaskAct(parmsUrl[&#x27;taskActID&#x27;]);
            act = await cmpage.model(&#x27;flow/act&#x27;).getActById(taskAct.c_act);
        }
        //debug(task,&#x27;page.htmlGetTaskActBtns - task&#x27;);
        //debug(act,&#x27;page.htmlGetTaskActBtns - act&#x27;);
        if(act.id &gt;0){
            //验证当前用户是否有该节点的权限
            let actAssign = await cmpage.model(&#x27;flow/act_assign&#x27;).getAssignByUser(act.id,this.mod.user, task.c_creater);
            debug(actAssign,&#x27;page.htmlGetTaskActBtns - actAssign&#x27;);
            if(think.isEmpty(actAssign))   return [];

            let form = think.isEmpty(act.c_form) ? {} : cmpage.objFromString(act.c_form);
            debug(form,&#x27;page.htmlGetTaskActBtns - form&#x27;);
            if(form.hasOwnProperty(&#x27;modulename&#x27;) &amp;&amp; form[&#x27;modulename&#x27;] === this.mod.c_modulename ){
                //本表单是流程节点需要打开的表单
                let btns = cmpage.arrFromString(act.c_form_btn);
                for(let btn of btns){
                    btn.label = think.isEmpty(btn[&#x27;label&#x27;]) ? act.c_name : btn.label;
                    btn.class = think.isEmpty(btn[&#x27;class&#x27;]) ? &#x27;btn-green&#x27; : btn.class;
                    btn.icon = think.isEmpty(btn[&#x27;icon&#x27;]) ? &#x27;cogs&#x27; : btn.icon;
                    if(!think.isEmpty(btn[&#x27;onclick&#x27;])){
                        btn.onclick = btn.onclick.replace(/#taskID#/g,task.id).replace(/#taskActID#/g,taskAct.id);;
                        html.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;${btn.class}&quot; data-icon=&quot;${btn.icon}&quot; onclick=&quot;${btn.onclick}&quot;&gt;${btn.label}&lt;/button&gt;&#x60;)
                    }
                    else if(!think.isEmpty(btn[&#x27;url&#x27;])){
                        btn.title = think.isEmpty(btn[&#x27;title&#x27;]) ? btn.label : btn.title;
                        btn.opentype = think.isEmpty(btn[&#x27;opentype&#x27;]) ? &#x27;dialog&#x27; : btn.opentype;
                        btn.url = btn.url.replace(/#taskID#/g,task.id).replace(/#taskActID#/g,taskAct.id);
                        html.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;${btn.class}&quot; data-icon=&quot;${btn.icon}&quot; data-toggle=&quot;${btn.opentype}&quot;
                        data-options=&quot;{id:&#x27;flowDialog&#x27;, url:&#x27;${btn.url}&#x27;, title:&#x27;${btn.title}&#x27;}&quot;&gt;${btn.label}&lt;/button&gt;&#x60;)
                    }else {
                        html.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;${btn.class}&quot; data-icon=&quot;${btn.icon}&quot;
                            onclick=&quot;return fwRunAct(${taskAct.id},true,&#x27;${this.mod.c_modulename}&#x27;);&quot;&gt;${btn.label}&lt;/button&gt;&#x60;)
                    }
                }
                if (task.c_link_type !== this.mod.c_table) {
                    debug(taskAct,&#x27;page.htmlGetActBtns - taskAct&#x27;);
                    if(taskAct.c_status === cmpage.enumTaskActStatus.WAIT) {
                        //默认的保存或者审核通过按钮
                        let reloadUrl = &#x60;/cmpage/page/edit?modulename=${this.mod.c_modulename}&amp;taskActID=${parmsUrl.taskActID}&amp;status=${parmsUrl.status}&amp;listIds=&#x60;;
                        html.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;btn-green&quot;  data-icon=&quot;save&quot;
                                onclick=&quot;return pageSaveByTask(&#x27;${this.mod.c_modulename}&#x27;,&#x27;${reloadUrl}&#x27;,
                                &#x27;${think.isEmpty(this.mod.c_other.editSaveAfter) ? &#x27;&#x27; : this.mod.c_other.editSaveAfter}&#x27;);&quot;&gt;
                                ${think.isEmpty(this.mod.c_other.editSaveLabel) ? &#x27;保存&#x27; : this.mod.c_other.editSaveLabel}&lt;/button&gt;&#x60;);
                    }else{
                        html.push(&#x27;&lt;label style=&quot;color: red;&quot;&gt;本操作已经执行完毕！&lt;/label&gt;&#x27;)
                    }
                }
            }else if(task.c_link_type === this.mod.c_table){
                //本表单是流程的关联主表单，则显示本流程节点的调用按钮
                let btn = think.isEmpty(act.c_call_btn) ? {}:eval(&#x60;(${act.c_call_btn})&#x60;);
                btn.label = think.isEmpty(btn[&#x27;label&#x27;]) ? act.c_name : btn.label;
                btn.class = think.isEmpty(btn[&#x27;class&#x27;]) ? &#x27;btn-green&#x27; : btn.class;
                btn.icon = think.isEmpty(btn[&#x27;icon&#x27;]) ? &#x27;cogs&#x27; : btn.icon;
                let form =eval(&quot;(&quot;+ act.c_form +&quot;)&quot;);
                form.title = think.isEmpty(btn[&#x27;title&#x27;]) ? btn.label : btn.title;
                form.opentype = think.isEmpty(btn[&#x27;opentype&#x27;]) ? &#x27;dialog&#x27; : btn.opentype;
                if(!think.isEmpty(form[&#x27;modulename&#x27;])){
                    form.url = &#x60;/cmpage/page/edit?modulename=${form[&#x27;modulename&#x27;]}&amp;id=0&amp;taskID=${task.id}&amp;taskActID=${taskAct.id}&amp;status=${act.c_domain_st}&#x60;;
                }
                form.url = form.url.replace(/#taskID#/g,task.id).replace(/#taskActID#/g,taskAct.id);
                html.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;${btn.class}&quot; data-icon=&quot;${btn.icon}&quot; data-toggle=&quot;${form.opentype}&quot;
                        data-options=&quot;{id:&#x27;flowDialog&#x27;, url:&#x27;${form.url}&#x27;, title:&#x27;${form.title}&#x27;, mask:true}&quot;&gt;${btn.label}&lt;/button&gt;&#x60;)
            }
            //增加可终止或者可挂起按钮
            if(taskAct.c_status == cmpage.enumTaskActStatus.WAIT){
                if(act.c_can_terminate){
                    html.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;btn-red&quot; data-icon=&quot;stop&quot; onclick=&quot;return fwTerminate(${taskAct.c_task},&#x27;${this.mod.c_modulename}&#x27;);&quot;&gt;终止&lt;/button&gt;&#x60;)
                }
                if(act.c_can_suspend){
                    html.push(&#x60;&lt;button type=&quot;button&quot; class=&quot;btn-orange&quot; data-icon=&quot;pause&quot; onclick=&quot;return fwSuspend(${taskAct.id},&#x27;${this.mod.c_modulename}&#x27;);&quot;&gt;挂起&lt;/button&gt;&#x60;)
                }
            }

        }

        return html;
    }


    /**
     * 编辑页面保存,&lt;br/&gt;
     * 如果是多个表的数据产生的编辑页，则根据存在于this.mod.c_table中的列更新表，一般需要在子类中继承，例如： admin/user:pageSave
     * @method  pageSave
     * @return {object} 如果有验证错误，则返回格式： {statusCode:300, message:&#x27;xxxxxx&#x27;}
     * @param  {object} parms 前端传入的FORM参数
     */
    async pageSave(parms){
        debug(parms,&#x27;page.pageSave - parms - 递交的内容&#x27;)
        //cmpage.debug(this.modEdits,&#x27;this.mod.pageSave - this.modEdits&#x27;)
        this.rec = {};
        for(let edit of this.modEdits){
            if(edit.c_editable &amp;&amp; edit.c_column.indexOf(&#x27;c_&#x27;)===0 ) {      //&amp;&amp; this.isExistColumn(edit.c_column,colList)
                if(edit.c_type === &#x27;checkbox&#x27;){
                    this.rec[edit.c_column] = think.isEmpty(parms[edit.c_column]) ? false : parms[edit.c_column];
                }else{
                    this.rec[edit.c_column] = parms[edit.c_column];
                }
            }
        }
        //cmpage.debug(md,&#x27;page.pageSave - md - 保存内容&#x27;)
        if(this.mod.editID == 0){
            //let id = await this.query(cmpage.getInsertSql(md,this.mod.c_table) +&#x27; returning id;&#x27;);
            this.rec[this.pk] = await this.model(this.mod.c_table).add(this.rec);
            await this.pageSaveLog(parms,&#x27;add&#x27;);
        }else {
            await this.model(this.mod.c_table).where(&#x60;${this.pk}=${this.mod.editID}&#x60;).update(this.rec);
            this.rec[this.pk] = this.mod.editID;
            await this.pageSaveLog(parms,&#x27;update&#x27;);
        }
        return {statusCode:200, message:&#x27;保存成功！&#x27;};
    }

    /**
     * 保存后的操作日志记录,，通过重写可在子类中定制日志的格式
     * @method  pageSaveLog
     * @return {无}
     * @param  {object} parms 前端传入的FORM参数
     * @param {string} flag 操作的类型标志
     */
    async pageSaveLog(parms,flag){
        let log =[];
        let md = this.rec;
        if(flag === &#x27;add&#x27; ){
            for(let edit of this.modEdits){
                if(edit.c_editable ) {
                    log.push(&#x60;${edit.c_name}:${md[edit.c_column]}&#x60;);
                }
            }
            await cmpage.model(&#x27;admin/log&#x27;).addLog(this.mod.user, log.join(&#x27;, &#x27;),this.mod.id, md[this.pk], cmpage.enumStatusExecute.SUCCESS, cmpage.enumLogType.ADD);
        }else if(flag === &#x27;update&#x27;){
            debug(this.mod,&#x27;page.pageSaveLog - this.mod&#x27;);
            let oldMd = {};
            if(think.isEmpty(parms[&quot;old_record&quot;])){
                oldMd = await this.getDataRecord();
            }else{
                oldMd = JSON.parse(parms[&quot;old_record&quot;]);
            }
            //debug(oldMd,&#x27;page.pageSaveLog - oldMd&#x27;);
            log.push(&#x60;${this.pk}:${md[this.pk]}&#x60;);
            for(let edit of this.modEdits){
                if(edit.c_editable &amp;&amp; edit.c_column !==&#x27;c_time&#x27; &amp;&amp; edit.c_column !==&#x27;c_user&#x27; &amp;&amp; edit.c_column.indexOf(&#x27;c_&#x27;)===0 &amp;&amp; edit.c_type.indexOf(&#x27;readonly&#x27;) === -1) {
                    if(edit.c_coltype === &#x27;timestamp&#x27;){
                        md[edit.c_column] =  cmpage.datetime(md[edit.c_column],&#x27;yyyy-MM-dd HH:mm:ss&#x27;);
                        oldMd[edit.c_column] =  cmpage.datetime(oldMd[edit.c_column],&#x27;yyyy-MM-dd HH:mm:ss&#x27;);
                    }
                    //cmpage.debug(edit,&#x27;this.mod.pageSaveLog - edit - 值有变化的字段保存到日志&#x27;);
                    //cmpage.debug(md[edit.c_column],&#x27;this.mod.pageSaveLog - md[edit.c_column] &#x27;);
                    let newValue = cmpage.objToString(md[edit.c_column]).replace(/&#x27;/g,&#x27;&#x27;);
                    if(oldMd[edit.c_column] !=newValue) {
//                        console.log(cmpage.objToString(md[edit.c_column]));
                        log.push(&#x60;${edit.c_name}: ${oldMd[edit.c_column]} --&gt; ${newValue}&#x60;);
                    }else if(edit.c_column === &#x27;c_name&#x27;){
                        log.push(&#x60;c_name:${md.c_name}&#x60;);
                    }
                }
            }
//            console.log(log.join(&#x27;, &#x27;));
            await cmpage.model(&#x27;admin/log&#x27;).addLog(this.mod.user, log.join(&#x27;, &#x27;),this.mod.id, md[this.pk], cmpage.enumStatusExecute.SUCCESS,  cmpage.enumLogType.UPDATE);
        }
    }

    //判断某个列是否存在于某个表中
    isExistColumn(column, list){
        for(let col of list){
            if(col.column === column){
                return true;
            }
        }
        return false;
    }

    //替换备注设置中的特殊字符,需要组成SQL
    getReplaceToSpecialChar(memo){
        //let ret = memo.split(&#x27;*&#x27;).join(&#x27;\&amp;&#x27;).split(/##/).join(&quot;\&#x27;&quot;);
        if(think.isEmpty(memo)){
            return &#x27;&#x27;;
        }
        let parms = memo.split(&#x27;*&#x27;);
        if(parms.length &gt;1){
            for(let parm of parms){
                if(parm.indexOf(&#x27;[[&#x27;)==0){      // [[ 开头表示从parmsUrl中取值
                    let key =parm.substr(2,parm.length -2).trim();
                    let parmsUrl = this.mod.parmsUrl;
                    let val = parmsUrl[&#x60;${key}&#x60;];
                    parms[parms.indexOf(parm)] = &#x60;${key}=${val}&#x60;;
                    //console.log(parms);
                }
            }
        }
        //let ret = memo.replace(/\*/ig,&#x27;\&amp;&#x27;).replace(/##/ig,&quot;\&#x27;&quot;);
        return parms.join(&#x27;\&amp;&#x27;).replace(/##/g,&quot;&#x27;&quot;);
    }

    /**
     * 取查看页面的设置，组合成列表数据的HTML输出&lt;/br&gt;
     * 如果需要改变查看页面的逻辑，可以重写本方法，或者修改 this.modCols的设置值后调用 super.htmlGetView()
     * @method  htmlGetView
     * @return {string} HTML页面片段
     * @param {boolean} [isPrintStyle] 是否是打印的风格
     */
  async htmlGetView(isPrintStyle) {
      isPrintStyle = !think.isEmpty(isPrintStyle);
    let html = [];
    if(this.mod.editID &lt;=0){
      return &#x27;&lt;tr&gt;&lt;td&gt;----&lt;/td&gt;&lt;td&gt;----&lt;/td&gt;&lt;td&gt;----&lt;/td&gt;&lt;td&gt;该数据不存在！&lt;/td&gt;&lt;td&gt;----&lt;/td&gt;&lt;td&gt;----&lt;/td&gt;&lt;td&gt;----&lt;/td&gt;&lt;/tr&gt;&#x27;;
    }
    let list = await this.query(&#x60;select ${this.getListFields()} from ${this.mod.c_datasource} where ${this.pk}=${this.mod.editID}&#x60;);
    let md =list[0];
        //cmpage.debug(md);
    html.push(&#x27;&lt;tr&gt;&#x27;);
    let k =0;
    for(let col of this.modCols){
      if (!col.c_isview ){
        continue;
      }
      //html.push(&#x60;&lt;td ${think.isEmpty(col.c_style) ? &quot;&quot;:&quot;style=&quot; + col.c_style}&gt;
      if(isPrintStyle){
          html.push(&#x60;&lt;td class=&quot;td3&quot; width=&quot;21%&quot;&gt; ${col.c_name}&lt;/td&gt;&lt;td&gt;&#x60;);
      }else{
          html.push(&#x60;&lt;td&gt; &lt;label class=&quot;control-label x85&quot;&gt;${col.c_name}: &lt;/label&gt;&#x60;);
      }
      if (col.c_type === &quot;checkbox&quot;){
        //   if(isPrintStyle){
        //       html.push(md[col.c_column] ? &quot;是&quot; : &quot;否&quot;);
        //   }else{
              html.push(&#x60;&lt;input type=&quot;checkbox&quot;  data-toggle=&quot;icheck&quot; value=&quot;1&quot; disabled  ${md[col.c_column] ? &quot;checked&quot; : &quot;&quot;} /&gt;&#x60;);
//          }
      }else if (col.c_type === &quot;kindeditor&quot;) {
        html.push(&#x60;&lt;div style=&quot;display: inline-block; vertical-align: middle;&quot;&gt;${md[col.c_column]} &lt;/div&gt;&#x60;);
      }else if(col.c_type === &quot;html&quot;){
        let input = think.isEmpty(col.c_memo) ? md[col.c_column] : col.c_memo.replace(/#value#/ig,md[col.c_column]);
        //debug(input,&#x27;page.htmlGetView - input.html&#x27;);
        html.push(input);
      }else if (col.c_coltype === &quot;decimal&quot;) {
        html.push(cmpage.formatNumber(md[col.c_column], {pattern: col.c_format}));
      } else if(col.c_coltype === &quot;timestamp&quot;) {
        html.push(cmpage.datetime(md[col.c_column],col.c_format));
      } else if(col.c_coltype === &quot;date&quot;) {
        html.push(cmpage.datetime(md[col.c_column],&#x27;yyyy-MM-dd&#x27;));
      } else if (col.c_type === &quot;replace&quot; &amp;&amp; !(/^select/.test(col.c_memo))) {
          html.push(await this.getReplaceText(md[col.c_column], col.c_memo));
      } else  {
        html.push(md[col.c_column]);
      }
      html.push(&#x27;&lt;/td&gt;&#x27;);
      k +=1;
      if(k &gt;= (this.mod.user.listColumns === cmpage.ui.enumListColumns.MOBILE ? 1 : this.mod.c_edit_column)){
          html.push(&#x27;&lt;/tr&gt;&lt;tr&gt;&#x27;);
          k =0;
      }
    }
    if(k&gt;0 &amp;&amp; k &lt;this.mod.c_edit_column &amp;&amp; isPrintStyle){
        html.push(&#x27;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&#x27;);
    }
    html.push(&#x27;&lt;/tr&gt;&#x27;);
    //debug(html.join(&#x27; &#x27;),&#x27;page.htmlGetView - return&#x27;);
    return html.join(&#x27; &#x27;);
  }

  async htmlGetViewBtn(){
      let html =[];
      let listIds = this.mod.listIds.split(&#x27;,&#x27;);
      if (listIds.length &gt; 0) {
          let prevID = 0, nextID = 0;
          let k = 0;
          for (let id of listIds) {
              if (id == this.mod.editID) {
                  k = listIds.indexOf(id);
                  break;
              }
          }
          if (k &gt; 0) {
              prevID = listIds[k - 1];
          }
          if (k &lt; listIds.length - 1) {
              nextID = listIds[k + 1];
          }
          html.push(&#x60;&lt;li class=&quot;left&quot; style=&quot;margin-left: -40px;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn-default&quot; ${k == 0 ? &#x27;style=&quot;display:none&quot;&#x27; : &#x27;&#x27;} data-icon=&quot;arrow-left&quot;
                  onclick=&quot;return pageGotoView(&#x27;${this.mod.c_modulename}&#x27;,${prevID});&quot;&gt;上一条&lt;/button&gt;&lt;/li&gt;&#x60;);
          html.push(&#x60;&lt;li class=&quot;left&quot; &gt;&lt;button type=&quot;button&quot; class=&quot;btn-default&quot; ${nextID == 0 ? &#x27;style=&quot;display:none&quot;&#x27; : &#x27;&#x27;} data-icon=&quot;arrow-right&quot;
                  onclick=&quot;return pageGotoView(&#x27;${this.mod.c_modulename}&#x27;,${nextID});&quot;&gt;下一条&lt;/button&gt;&lt;/li&gt;&#x60;);
      }
      html.push(&#x27;&lt;li&gt;&lt;button type=&quot;button&quot; class=&quot;btn-close&quot; data-icon=&quot;close&quot;&gt;关闭&lt;/button&gt;&lt;/li&gt;&#x27;);
      return html.join(&#x27;&#x27;);
  }

  /**
   * 取查看页面的设置，组合成打印页面的HTML输出
   * @method  htmlGetPrint
   * @return {string} HTML页面片段
   */
    async htmlGetPrint() {
        let html = [];
        //主表部分
        html.push(&#x27;&lt;table class=&quot;printTable&quot; style=&quot;BORDER-COLLAPSE: collapse&quot; bordercolor=&quot;#000000&quot; cellSpacing=0 width=&quot;100%&quot; align=&quot;center&quot; bgcolor=&quot;#FFFFFF&quot; border=&quot;1&quot;&gt;&#x27;);
        html.push(await this.htmlGetView(true));
        html.push(&#x27;&lt;/table&gt;&#x27;);
        return html.join(&#x27;&#x27;);
    }

    /**
     * 删除记录,&lt;br/&gt;
     * 子类中可以重写本方法，实现其他的删除逻辑，如判断是否可以删除，删除相关联的其他记录等等
     * @method  pageDelete
     * @return {object} 记录对象
     */
    async pageDelete(){
        let ret={statusCode:200,message:&#x27;删除成功！&#x27;,data:{}};

        if(this.mod.recID &gt;0){
            if(think.isEmpty(this.mod.flag)){
                await this.model(this.mod.c_table).where(&#x60;${this.pk}=${this.mod.recID}&#x60;).update({c_status:-1});
            }else {
                await this.model(this.mod.c_table).where(&#x60;${this.pk}=${this.mod.recID}&#x60;).delete();
            }
        }
        return ret;
    }

    /**
     * 取分页列表的 footer 设置，组合成HTML输出，一般不需要重写本方法
     * @method  htmlGetFooter
     * @return {string}  HTML片段
     */
    htmlGetFooter() {
        if(this.mod.c_pager){
            let cnt = this.mod.user.listColumns === cmpage.ui.enumListColumns.MOBILE ?
                &#x60;${this.mod.pageSize &gt; this.list.count ? this.list.count: this.mod.pageSize} / ${this.list.count}&#x60; : &#x60;每页&amp;nbsp;${this.mod.pageSize}&amp;nbsp;条，共  ${this.list.count} 条&#x60;;
            return &#x60;&lt;div class=&quot;bjui-pageFooter&quot;&gt;
                &lt;div class=&quot;pages&quot;&gt;
                    &lt;span&gt;${cnt}&lt;/span&gt;
                &lt;/div&gt;
                &lt;div class=&quot;pagination-box&quot; data-toggle=&quot;pagination&quot; data-total=&quot;${this.list.count}&quot; data-page-size=&quot;${this.mod.pageSize}&quot;
                 data-page-current=&quot;${this.mod.pageIndex}&quot; data-page-next=&quot;&quot;&gt;
                &lt;/div&gt;
            &lt;/div&gt;&#x60;;
        }
        return &#x27;&#x27;;
    }

    /**
     * 修改状态，供界面按钮直接调用，工作流相关方法（状态流转类）&lt;/br&gt;
     * 子类中覆写本方法，可以根据业务对象的状态增加其他逻辑
     * @method  updateStatus
     * @return {object} 结果输出
     * @params {int} id 记录ID
     * @params {int} actID 流程节点ID
     * @params {int} status 状态值，一般在t_code表中设置
     * @params {boolean} isSelf 自身表单的调用，区别于其他模块的调用
     */
    async updateStatus(id, actID, status, isSelf){
        debug(id,&#x27;page.updateStatus - id&#x27;);
        if(id &gt;0 &amp;&amp; actID &gt;0 &amp;&amp; status &gt;0){
            let rec = {c_status:status,c_act:actID,c_user:this.mod.user.id, c_time:think.datetime()};

            await this.model(this.mod.c_table).where(&#x60;${this.pk}=${id}&#x60;).update(rec);
            return {statusCode:200, message:&#x27;操作执行成功！&#x27;}
        }
        return {statusCode:300,message:&#x27;参数错误!&#x27;}
    }

    /**
     * 取模块列表的显示列设置，组合成时间轴HTML输出，一般在子类中通过重写这个方法来达到页面定制的效果
     * @method  htmlGetListTimeline
     * @return  {string}  HTML片段
     */
    async htmlGetListTimeline() {
        let html = [];

        await this.getDataList();
        //debug(this.list.data, &#x27;page.htmlGetListTimeline - this.list.data&#x27;);
        for(let row of this.list.data){
            //debug(row, &#x27;page.htmlGetListTimeline - row&#x27;+this.list.data.indexOf(row));
            //处理替换值
            for(let col of this.modCols){
                if (col.c_type === &quot;replace&quot; &amp;&amp; !(/^select/.test(col.c_memo))) {
                    //debug(col, &#x27;page.htmlGetListTimeline - col&#x27;+this.modCols.indexOf(col));
                    row[col.c_column] = await this.getReplaceText(row[col.c_column], col.c_memo);
                }else if(col.c_coltype === &#x27;timestamp&#x27;){
                    row[col.c_column] = think.datetime(row[col.c_column]);
                }
            }
            html.push(&#x27;&lt;li&gt;&#x27;);
            html.push(&#x60;&lt;div class=&quot;time&quot;&gt;${row.c_time}&lt;/div&gt;&#x60;);
            html.push(&#x60;&lt;div class=&quot;version&quot;&gt;${row.c_status}&lt;/div&gt;&#x60;);
            html.push(&#x60;&lt;div class=&quot;number&quot;&gt;&lt;/div&gt;&#x60;);
            html.push(&#x60;&lt;div class=&quot;content&quot;&gt;&lt;pre&gt;${think.isEmpty(row.c_desc) ? &#x27;&#x27;:&#x27;批注说明： &#x27;+row.c_desc}
${think.isEmpty(row.c_memo) ? &#x27;&#x27;:&#x27;其他备注： &#x27; +row.c_memo}&lt;/pre&gt;&lt;/div&gt;&#x60;);
            html.push(&#x27;&lt;/li&gt;&#x27;);
        }

        return html.join(&#x27; &#x27;);
    }

    /**
     * 根据参数ID取参数的名称，一般用于页面模块配置中的‘替换’调用: admin/cdoe:getNameById &lt;/br&gt;
     * 子类中重写的时候需要为 this.mod.c_table 和 this.pk 赋值，因为直接调用的时候进行模块设置的初始化 &lt;/br&gt;
     * 当然也可以重写 constructor 设置这两个值
     * @method  getNameById
     * @return {string}  参数名称
     * @param {int} id  参数ID
     * @param   {string} fieldNames 字段名称,逗号分隔
     * @param   {string} joinStr 连接的字符串
     */
    async getNameById(id,tableName,pk,fieldNames,joinStr){
        let rec =await this.model(this.mod.c_table).where(&#x60;${this.pk}=${id}&#x60;).find();
        //debug(rec,&#x27;page.getNameById - rec&#x27;);
        if(think.isEmpty(rec))  return &#x27;&#x27;;
        if(think.isEmpty(fieldNames)){
            return rec.c_name;      //默认返回 c_name 字段值
        }else{
            return cmpage.strGetValuesByPropertyName(rec,fieldNames,joinStr)
        }
    }

}

    </pre>
</div>

                </div>
            </div>
        </div>
    </div>
<a id="gotoTop" class='well well-small' href='#'>
    Top
</a>
<script src="../assets/vendor/jquery/jquery-1.8.2.min.js"></script>
<script src="../assets/vendor/bootstrap/js/bootstrap.min.js"></script>
<script src="../assets/vendor/prettify/prettify-min.js"></script>
<script src="../assets/js/config.js"></script>
<script src="../assets/js/doc.js"></script>
</body>
</html>
